Sometimes when writing javascript for use with Max/MSP I find I need to reuse bits of code that I’ve already created for a different project. Most of the time a simple search, copy and paste suffices but in some situations it would be better to have the ability to import other javascript files to get access to all of the functions they contain. This would also be useful when trying to organise where you files are stored. I don’t always want my javascripts in the Max search path (too many files here will cause the program to take ages to load), and I don’t always want them in the same directory as my main patch (which is the default place Max will look for a javascript/abstraction/image). The following code will import a specified javascript file into the current one.
You can use absolute or relative paths, the comment in the code gives you examples of how to navigate through directories in both directions. Please be a bit careful as the code takes advantage of the eval() function so if one of the files you include contains a mistake or something that is badly formatted then this will be included as it exists already. You should save this file in the Cycling ’74 > jsextensions folder so it will be available any time you need it.
/*
* lh.jsextensions
*
* first argument must be "this" to set scope
* second argument specifies the file to include
* relative paths must start wih a "/" separator
* this function uses eval() so please be careful
*
* include(this,"/local.js"); // same directory
* include(this,"/lib/functions/below.js"); // navigate lower
* include(this,"/../../above.js"); // navigate higher
* include(this,"/../../sub1/sub2/both.js"); // combine both
* include(this,"Macintosh HD:/Users/directory/sub-directory/other.js"); // absolute path
*/
function include(scope,dest) {
var mem = "";
var struct = /((\/\.\.)*)(.+$)/;
var parent = /(.+)\/[^.]+\.\w+$/;
var levels = struct.exec(dest)[1].length/3;
var name = struct.exec(dest)[3];
var target;
if (dest.charAt(0) != "/") {
target = dest;
} else if (!levels) {
target = scope.patcher.filepath.match(parent)[1]+name;
} else {
target = scope.patcher.filepath;
for (i=-1; i<levels; i++) {
target = target.slice(0,target.lastIndexOf("/",target.length-2));
}
target += name;
}
var f = new File(target,"read","TEXT");
f.open();
if (f.isopen) {
while(f.position<f.eof) {
mem += f.readline(800)+"\n";
}
f.close()
} else {
var er_file = target.slice(target.lastIndexOf("/",target.length-2)+1);
var er_path = target.slice(0,target.lastIndexOf("/",target.length-2)+1);
post("Error importing file \""+er_file+"\" from \""+er_path+"\"\n");
}
scope.eval(mem);
}
// EOF
3 Comments
wow, really nice articles running here!
i was wondering how to do this in max, but couldn’t find in the manual.
tks for sharing!
Luke,
Are you still able to do this in Max 6? Looks like they’ve disabled the eval() function…
Javascript TypeError: scope.eval is not a function, line 506
I don’t have Max6 yet so I cannot check, however there are numerous JSON parsing libraries available that you could use instead. I think there are even a few examples posted to the forum. If you download that example it should be fairly easy to copy the relvant code across to use instead. Let me know how it goes!