Using JS "import" for modular code

Find out why the . goes before the /

Moderator: Paul Tuersley

Post Reply
Darkmoon_UK
Posts: 62
Joined: September 5th, 2006, 3:45 am
Location: Chiswick, London, UK
Contact:

EDIT: See my reply below to jump straight to the solution

I expect that many of us, myself included, have a few functions that we repeatedly use when scripting. One of the features of Javascript I've most wanted to use is to 'import' other JavaScript files, so that I can keep one updateable library of common functions, and refer to this from other scripts.

Although Im a long time Java coder, AE is my first exposure to JavaScript so I may be doing it wrong, but this command just doesn't seem to work in AE. It accepts the command, and picks up syntax errors if I don't form it right, but it doesn't seem to have any effect. What am I doing wrong?

A.jsx:

Code: Select all

import B.jsx
alert(Bfunction());
B.jsx:

Code: Select all

function Bfunction()
{
	return "success";
}
*Awaits a beating with the 'schoolboy error' stick*
Last edited by Darkmoon_UK on December 6th, 2007, 10:08 am, edited 5 times in total.
Darkmoon_UK
Posts: 62
Joined: September 5th, 2006, 3:45 am
Location: Chiswick, London, UK
Contact:

Ok, I think I have got to the bottom of this, and discovered something interesting about JavaScript in the process...

Firstly, the Mozilla JavaScript Reference states that AE's version of ECMAScript does not support import and export functions:

Mozilla Reference: http://developer.mozilla.org/en/docs/Co ... nts:import
Adobe Reference: "After Effects scripting is based on ECMAScript (or more specifically, the 3rd Edition of the ECMA-262 Standard)."

So, where does that leave us? Fortunately, before despair set in, I came across another method for importing script from other files, detailed here:

http://www.webreference.com/programming/javascript/mk/

Like most JavaScript examples on the web, it's heavily browser-based. The principal idea of using the eval() function to import another file is a brilliant one though, and easily adapted to an even simpler bit of AE script.

A.jsx

Code: Select all

importJsx("B.jsx");

alert(Bfunction());

function importJsx(fileName)
{
	var f = new File(fileName).open('r');
	f.open('r');
	var toImport = f.read();
	f.close();
	return eval(toImport);
}
B.jsx

Code: Select all

function Bfunction()
{
	return "success";
}
Using this method, you need only need paste one simple, unchanging function into each of your scripts, with a file reference to your library of functions. This will save you time pasting code, and allow older scripts to automatically benefit from improvements you may make to common functions as time goes on. The pitfall of this is that if you accidently change the behaviour of one of your functions, you may break the behaviour of your older scripts. When maintaining a function library file, you should always keep running backups so you can fall back on an earlier version if necessary.

The 'something interesting' that I mentioned earlier, was learning how to eval() the imported code into the top level of our script. Originally, I called eval() from within the body of the ImportJsx() function, which resulted in the functions loaded from B.jsx only becoming defined within the scope of the ImportJsx() function, clearly not what we want. Then it hit me: we want to return the evaluated code to wherever the function was called. Which works!

Update: For sheer pasteability alone, this somewhat hacky code gets it down to one line which can be pasted at the top of your scripts, without the need to define any functions:

Code: Select all

eval((f=new File("myFunctionLibrary.jsx")).open('r')?f.read()+(f.close()?"":""):alert("Import failed"));
Hope you find this useful... This technique is key to a super useful and secret script due for release soon on AEnhancers. (clue: Excel) :wink:
Darkmoon_UK
Posts: 62
Joined: September 5th, 2006, 3:45 am
Location: Chiswick, London, UK
Contact:

Here's that Script Release I mentioned: http://chrishatton.homeip.net/?page_id=42
Last edited by Darkmoon_UK on January 25th, 2008, 5:21 am, edited 1 time in total.
Dan Ebberts
Posts: 320
Joined: June 26th, 2004, 10:01 am
Location: Folsom, CA
Contact:

Any reason you don't just use the #include file directive?

For example, your main script might include this:

#include "myinclude.jsxinc"

And the include file (located in the same folder in this example) might look like this:

alert("It works!");

Try it - it works great. Remember to use the jsxinc suffix on the included file and specify the path if its in a different folder than your main script.

Dan
Darkmoon_UK
Posts: 62
Joined: September 5th, 2006, 3:45 am
Location: Chiswick, London, UK
Contact:

Care to tell me where that was documented before I go and quietly shoot myself?

Thanks Dan :-)
Dan Ebberts
Posts: 320
Joined: June 26th, 2004, 10:01 am
Location: Folsom, CA
Contact:

It's in the JavaScript Tools Guide in the Bridge documentation. Look in the Modular Programming Support section of the ExtendScript Tools and Features chapter.

Dan
Darkmoon_UK
Posts: 62
Joined: September 5th, 2006, 3:45 am
Location: Chiswick, London, UK
Contact:

The Bridge guide... should have read the Bridge guide *silently rocks*
Post Reply