node require json persisting across files - json

In one of my files, A.js, I call var locations = require('./locations.json'). I then modify locations.
Then in a different file I have the same thing var locations = require('./locations.json'). However instead of locations having the value of what is stored in locations.json, it now contains the changes that I made in A.js.
A.js
var locations = require('./locations.json')
function func() {
// Changing the values stored locations
}
B.js
var locations = require('./locations.json')
console.log(locations) // prints out the changes made in A.js instead of what is in locations.json
Why does this happen and is there any way around it?

Because require is for module loading, and only loads a single copy of whatever you pass it, and keeps a reference to it. See http://fredkschott.com/post/2014/06/require-and-the-module-system/ for technical details.
If you do want to simply load the json file use fs.readFileSync instead, eg:
var locations = fs.readFileSync('./locations.json');

Related

How do you POST files in chunks, to server, using input id as param, in HTML/jQuery?

Description
I have a function that takes HTTP_POST path for server side hardcoded .js handler and file id from input[type=file]. I'm trying to POST that binary file to server but in chunks with no success.
What have you tried?
Using my uncle wisdom, I have noted that there is a way to slice the file using :
var File1 = document.querySelector('input').files[0].slice(0,7);
But passing this variable to the function is not an option since it takes id ="file_1" as a parameter from <input type="file">. Also, printing this variable doesn't work with console.log (half of you are already thinking to send me back to uni) hint: I've never studied Javascript. So I poked my uncle a little harder and found it. FileReader gives you the ability to actually read the inside, which gave me hope since my file was printed out to console.log
var reader = new FileReader;
reader.readAsBinaryString(File1);
reader.onload = function(e) {
var rawLog = reader.result;
console.log(rawLog);
};
At this point console.log gave me a print of first seven bytes, of my file. And by all of this we got to the question I wish to ask
Question ?¿
How to past this print as with input to the function so I can have this file sliced and saved?
You can slice off a piece of the file, use that piece to create a File object add it to a FileList and then overwrite the FileList from the input with the one that has your new file
var input = document.querySelector('input');
var originalfile = input.files[0];
var slice = originalfile.slice(0,7); // slice the file
var newfile = new File([slice] , 'slicedfile.dat'); // create new file
// Need to use a data transfer object to get a new FileList object
var datTran = new ClipboardEvent('').clipboardData || new DataTransfer();
datTran.items.add(newfile); // Add the file to the DT object
input.files = datTran.files; // overwrite the input file list with ours
// call function that takes path and id as parameters

Return Collection of Google Drive Files Shared With Specific User

I'm trying to get a collection of files where user (let's use billyTheUser#gmail.com) is an editor.
I know this can be accomplished almost instantly on the front-end of google drive by doing a search for to:billyTheUser#gmail.com in the drive search bar.
I presume this is something that can be done in Google App Scripts, but maybe I'm wrong. I figured DriveApp.searchFiles would work, but I'm having trouble structuring the proper string syntax. I've looked at the Google SDK Documentation and am guessing I am doing something wrong with the usage of the in matched to the user string search? Below is the approaches I've taken, however if there's a different method to accomplishing the collection of files by user, I'd be happy to change my approach.
var files = DriveApp.searchFiles(
//I would expect this to work, but this doesn't return values
'writers in "billyTheUser#gmail.com"');
//Tried these just experimenting. None return values
'writers in "to:billyTheUser#gmail.com"');
'writers in "to:billyTheUser#gmail.com"');
'to:billyTheUser#gmail.com');
// this is just a test to confirm that some string searches successfully work
'modifiedDate > "2013-02-28" and title contains "untitled"');
Try flipping the operands within the in clause to read as:
var files = DriveApp.searchFiles('"billyTheUser#gmail.com" in writers');
Thanks #theAddonDepot! To illustrate specifically how the accepted answer is useful, I used it to assist in building a spreadsheet to help control files shared with various users. The source code for the full procedure is at the bottom of this post. It can be used directly within this this google sheet if you copy it.
The final result works rather nicely for listing out files by rows and properties in columns (i.e. last modified, security, descriptions... etc.).
The ultimate purpose is to be able to update large number of files without impacting other users. (use case scenario for sudden need to immediately revoke security... layoffs, acquisition, divorce, etc).
//code for looking up files by security
//Posted on stackoverlow here: https://stackoverflow.com/questions/62940196/return-collection-of-google-drive-files-shared-with-specific-user
//sample google File here: https://docs.google.com/spreadsheets/d/1jSl_ZxRVAIh9ULQLy-2e1FdnQpT6207JjFoDq60kj6Q/edit?usp=sharing
const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FileList");
const clearRange = true;
//const clearRange = SpreadsheetApp.getActiveSpreadsheet().getRangeByName("ClearRange").getValue();
//if you have the named range setup.
function runReport() {
//var theEmail= SpreadsheetApp.getActiveSpreadsheet().getRangeByName("emailFromExcel").getValue();
//or
var theEmail = 'billyTheUser#gmail.com';
findFilesByUser(theEmail);
}
function findFilesByUser(theUserEmail) {
if(clearRange){
ss.getDataRange().offset(1,0).deleteCells(SpreadsheetApp.Dimension.ROWS)
}
var someFiles = DriveApp.searchFiles('"' + theUserEmail + '" in writers');
var aListOfFiles = []
while(someFiles.hasNext()){
var aFile = someFiles.next();
aListOfFiles.push([aFile.getId()
,aFile.getName()
,aFile.getDescription()
,aFile.getSharingAccess()
,aFile.getSharingPermission()
,listEmails(aFile.getEditors())
,listEmails(aFile.getViewers())
,aFile.getMimeType().replace('application/','').replace('vnd.google-apps.','')
,aFile.getDateCreated()
,aFile.getLastUpdated()
,aFile.getSize()
,aFile.getUrl()
,aFile.getDownloadUrl()
])
}
if(aListOfFiles.length==0){
aListOfFiles.push("no files for " + theUserEmail);
}
ss.getRange(ss.getDataRange().getLastRow()+1,1, aListOfFiles.length, aListOfFiles[0].length).setValues(aListOfFiles);
}
function listEmails(thePeople){
var aList = thePeople;
for (var i = 0; i < aList.length;i++){
aList[i] = aList[i].getEmail();
}
return aList.toString();
}

DriveApp.getRootFolder() is returning null to webapp

As part of a larger Google App Script webapp, I want to create a rudimentary file system with files/folders in the user's Google Drive. I'm doing this through a element where each would be a different folder (prefixed with a '*') or file.
I have setup the webapp HTML to include the element, but within this element I call a script that will populate the via a call to google.script.run.withSuccessHandler. It appears that this code runs as I'd expect, but the result of DriveApp.getRootFolder() is null, thereby making me unable to access the file structure.
// In the HTML file.
...
<head>
<script>
...
// Populate options in the file/folder list based on the provided folder.
function setFiles(folder)
{
alert(folder);
return;
/* // Get the select item.
var e = document.getElementById("file-select");
// First list all the folders at the top.
//#TODO Adding an asterick on folders to identify them for now, maybe have a different method later?
var folderI = folder.getFolders();
var i = 0;
while(folderI.hasNext())
{
var fldr = folderI.next();
e.innerHTML += "<option id='f_'" + i + "'>*" + fldr.getName() + "</option>";
i++;
}
// Now list all the files in the current directory.
i = 0;
var fileI = folder.getFiles();
while(fileI.hasNext())
{
var fle = fileI.next();
e.inner.HTML += "<option id='f_'" + i + "'>*" + fle.getName() + "</option>";
i++
}
*/
....
</script>
</head>
<body>
...
<div id="select-files">
<select id="file-select" size="10">
<script>
// Populate the initial file/folder list.
google.script.run.withSuccessHandler(setFiles).getRootFolder();
</script>
</select>
</div>
...
// In code.gs
/**
* Returns the root folder for the user.
* #return The root folder of the user.
*/
function getRootFolder()
{
return DriveApp.getRootFolder();
}
This is the code as I'm testing it now, hence my commenting out most of setFiles(). alert() results in 'null', but I'd expect it to be an 'Object [Object]' type that I could iterate through.
Interestingly, when I've added Logger.log() lines in the code.gs file, no log output is produced (I can't figure out why, because if I change the return value of getRootFolder() to a string, that string is displayed in the alert, so I know the code is entering that function correctly.
I'm wondering if this is a misunderstanding such that Google Drive (or maybe, generally, Google App Script specific objects) cannot be passed to an HTML file, though I couldn't find any clear documentation that this is the case.
As Cooper said in the comments, the Folder type is not legal to send to the client. If you look at what a Folder contains, it is purely functions, which are not allowed to be sent over.
All that client-side you commented out in setFiles cannot function in the user's browser. Even if you were able to pass the Folder code into the client, what would folder.getFolders() mean to the user's browser? It would start looking for the rest of the code from DriveApp, which doesn't exist in the browser, and still fail.
I'm wondering if this is a misunderstanding such that Google Drive (or maybe, generally, Google App Script specific objects) cannot be passed to an HTML file
What you get passed to the HTML file is documented here. Pay special attention to how google.script.run works.
No, you cannot pass the entire environment of your server-side code to the client (e.g. pass all of DriveApp and its dependences over to the client).
What you can do on both sides is construct your own version of Folder which exports the strings on the server side and reconstructs them on the client side. Note that arrays of strings are OK, so I would put things like the child, parent folder names and IDs in arrays. Just to be safe, I use JSON stringify/parse to strip functions out. This example works without the JSON part, but on more complicated objects it can be nice to clean them up.
client-side code
// just to log that it works
google.script.run.withSuccessHandler(response => {
response = JSON.parse(response);
console.log({response})
}).getFolder();
Code.gs
// client-code calls this to get folder info
function getFolder(id) {
return JSON.stringify(new Folder_(id ? DriveApp.getFolderById(id) : DriveApp.getRootFolder()));
}
// constructor for a `folder` suitable to send to the client
function Folder_(folder) {
this.id = folder.getId();
this.name = folder.getName();
this.foldersIds = [];
this.foldersNames = [];
this.parentsIds = [];
this.parentsNames = [];
this._extractFolders(folder, "folders");
this._extractFolders(folder, "parents");
}
// one function for both "getFolders" and "getParents"
Folder_.prototype._extractFolders = function(folder, type) {
var folders = folder["get" + type.replace(/^./, function(str){return str.toUpperCase()})]();
while (folders.hasNext()) {
var folder = folders.next();
this[type + "Ids"].push(folder.getId());
this[type + "Names"].push(folder.getName());
}
};

Getting undefined instance tree for DWFX file

We are trying to get all node elements of DWFX file but we are getting undefined instance tree for DWFX file. We have used below code to get each element id.
// Try to get instance tree for DWFX file
var model = this.viewer.model;
var modelData = model.getData();
var it = modelData.instanceTree; // get instance tree
We have used another way to get element node id for DWFX file. (In that case, we are getting only panel label id for DWFX file) But that logic is not working for all DWFX files.
// Try to get all ids for DWFX file
var model = this.viewer.model;
var modelData = model.getData();
var allIds = modelData.stringDbIds; // get all ids
Please us know If I am using wrong approach to get all elements for DWFX file.
You need to wait for Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT event to make sure the instanceTree is available in your loaded model:
viewer.addEventListener(Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, function () {
var model = this.viewer.model;
var modelData = model.getData();
var it = modelData.instanceTree;
console.log(it)
})
In some cases you may have to wait also for Autodesk.Viewing.GEOMETRY_LOADED_EVENT event if you intend to access geometry of the components. Here is an article that may be relevant: Asynchronous viewer events notification

How to get a document object from a file object in a Google-Apps Script

My problem is that I have a number of Google documents (docs) and each has a table of contents. I want to grab the TOC's and place them in another document. This should be easy, but I have run into a snag.
I can grab all of files in a folder with:
var folder = DocsList.getFolder('yourfolder');
var contents = folder.getFilesByType(DocsList.FileType.DOCUMENT);
This gives me an array of files as the variable 'contents'
Great.
I also know that
var TOC = **doc**.getAs(DocumentApp.ElementType.TABLE_OF_CONTENTS)
The problem is that I cannot figure out how to get a document object from a file object or alternately how to get an array of documents in a folder rather than an array of files.
I have searched for an answer and not only on this site. If anyone can help, I would appreciate it very much
DocsList and DocumentApp have at least one method in common which is that they have access to the ID of documents so it is quite straightforward to pass this ID parameter from one method to the other.
This code demonstrates :
function myFunction() {
var folder = DocsList.getFolder('yourfolder');
var contents = folder.getFilesByType(DocsList.FileType.DOCUMENT);
var docObject = [];
for(var c in contents){
docObject.push(DocumentApp.openById(contents[c].getId()));
}
Logger.log(docObject);// now you have an array of DocumentApp objects
}