JSX.js A Game Changer in Adobe HTML Extensions Development?

TrevorAdobe Extensions0 Comments

JSX.js is a simple api to significantly speedup and simplify your extensions development.

The manifest.xml is the file that instructs the CEP engine about the setup of the extension, in which host applications should it be run, what should be the dimensions of the UI if any, etc. etc. and the location of the "index.html" and "host.jsx", well thus goes the manual. The problem with the manual's approach is that every time you make a change in the host.jsx you have to restart the application to see the change*. Wouldn't it be nice if you could just at a click of a button and in an instance restart the extension so that all the changes in all the files** including the jsx files are reflected? Well it's dead simple, at least when someone's done the tough stuff for you. Also wouldn't it be nice if executing jsx scripts from the js engine was made really simple without the need of "quoting" + every + "other" + word? Wouldn't it be nice if when we run our jsx scripts they can know there own path? If the answer to those question is yes then continue reading otherwise adios amigos
* On some of the versions of some of the applications on Windows changes are reflected after closing and reopening the extension.
** Changes made in the manifest are not reflected, you need to restart the app for that one.

Compare the following 2 manifest snippets.

If you use the "Typical" method then 1) in order to have the extension reflect the changes you make you'll need to restart the host app and 2) you'll never really know what gets loaded first the js or the jsx (well maybe smarty pants out there does know). If you use the "Trevor" method then 1) you'll see the jsx changes reflected with a single click and 2) you'll know the order the 2 engines or run.
The "Trevor" method misses out the line <ScriptPath>./jsx/myFab.jsx</ScriptPath> so what do we do instead? JSX.js in particular the jsx.evalFile() method.
Note: Presently you need to set the <Parameter>--enable-nodejs</Parameter> CEFCommandLine option as illustrated above. At some point in the distant future I might make it independent of NodeJs.

JSX.js has 2 methods jsx.evalFile(file); for executing jsx snippets and jsx.evalScript(script); for executing jsx files.
jsx.evalFile(file, callback, replacements, forceEval);

PARAMETERS:

The 4 parameters file callBack replacements and forceEval can be entered in any order. One can if one is interested for readability purposes use a single object, in which each parameter has multiple keys that can be used for then that can be either lowercase or camelCase.
One can also use the lowercase jsx.evalfile() or shorthand jsx.file() instead of the camelCase jsx.evalFile()

file Type: String
Description: The path of the jsx file to be executed. Can be an absolute path or path relative to the extensions folder or a file in the extensions jsx folder.

callBack Type: Function [Optional Default: None]

Description: The callback function that receives the result from the jsx script.
The result will always be a string so you might need to eval it in the callback function.
See the not by the forceEval parameter on callbacks with InDesign.

replacements Type: Object [Optional Default: None]

Description: The replacements that you might want made. In the jsx file surround words you want replaced with __ like __this__ and __that__ and then you make your replacement object where the keys are the strings you want replace and the values are their replacements.

forceEval Type: Boolean [Optional Default: false]

Description: This wraps the script in an eval What for? The callback as mentioned above can only accept a String. All the apps pass the result of the script as a String except for InDesign unless the script explicitly returns a string. Let's compare the following 2 scripts. Script 1 (length 1 byte) 1, Script 2 (length 3 bytes) '1' Script 1 will in all the apps except for InDesign pass the 1 to the callback, in InDesign the callback will be triggered but the 1 will not be received In Script 2 even InDesign will will pass the 1 to the callback because it was explicitly passed as a string. 2 methods of non-explicitly forcing the result to be a string are 1) to run the script using $.evalFile() and 2) to wrap the script in an eval. By default the jsx.evalFile() method will execute the jsx script using $.evalFile() and therefore even InDesign will return the result as a String however when replacements are made then $.evalFile() is not used and therefore unless the result was explicitly set as a String InDesign will not receive the result. Setting the forceEval to true will wrap the script in an eval and therefore for the result to be a String
Summary: Don't set forceEval to true unless you are 1) Using InDesign and 2) Using replacements and 3) Not explicitly passing the result as a string and 4) You need the result.

NOTE: When you execute the jsx script using the "Typical" manifest.xml method the $.fileName will not return the file's path. When using jsx.evalFile() the correct* Path will be returned unless replacements have passed. To return the correct path in all cases you can use $.__fileName('baseName') where baseName is the files baseName without the path. In most cases $.__fileName() without the baseName will also work, see below for the exceptions.
*If on a Mac you have a root folder and a volume of the same name, for example you have the root folder /myScripts and you have a volume /Volumes/myScripts and your script has the path /Volumes/myScripts/myScript.jsx then $.fileName will give the wrong path /myScripts/myScript.jsx. The correct path will be returned if you use $.__fileName('myScript.jsx'). If you just use $.__fileName() without the baseName then the same wrong path will be given as by the $.fileName property. In InDesign $.__fileName() without the baseName will only return the correct path if no other script has be executed using the jsx.evalFile() method after the current script has be executed. The other apps don't have this issue and all the apps including InDesign $.__fileName('myScript.jsx') will return the correct path. The only case where it won't is if you executed multiple jsx files using the jsx.evalFile() on files with different paths and the same baseName. So either avoid doing that or use $.__fileName() without the basename subject to it's limitations.
$.__fileName('baseName') will only work for scripts executed using the jsx.evalFile() method. A new property $.__dirname will be available to all jsx scripts run in the extension's target engine as long as JSX.js loaded first.

RETURNS: Boolean
Description: Will return true if the js engine could process the jsx.evalFile() command and false if it couldn't (like the file didn't exist). True will be returned even if the jsx engine cannot execute the script (like if (5 = 3){2}).

jsx.evalScript(script, callback, replacements, forceEval);

PARAMETERS:

The 4 parameters script callBack replacements and forceEval can be entered in any order. One can if one is interested for readability purposes use a single object, in which each parameter has multiple keys that can be used for them that can be either lowercase or camelCase.
One can also use the lowercase jsx.evalscript() or the shorthand jsx.eval() or jsx.script() instead of the camelCase jsx.evalScript()

script Type: String
Description: The jsx script to be executed.
Like csInterface.evalScript() you need to escape \

callBack Type: Function [Optional Default: None]

Description: The callback function that receives the result from the jsx script.
The result will always be a string so you might need to eval it in the callback function.
InDesign does not by default pass the result as a string so you need to either pass the result explicitly as a string or set the forceEval to true if you need the result from InDesign, see more details of this by the forceEval description.

replacements Type: Object [Optional Default: None]

Description: The replacements that you might want made. Surround words you want replaced with __ like __this__ and __that__ and then you make your replacement object where the keys are the strings you want replace and the values are their replacements.

forceEval Type: Boolean [Optional Default: false]

Description: This wraps the script in an eval What for? The callback as mentioned above can only accept a String. All the apps pass the result of the script as a String except for InDesign unless the script explicitly returns a string. Let's compare the following 2 scripts. Script 1 (length 1 byte) 1, Script 2 (length 3 bytes) '1' Script 1 will in all the apps except for InDesign pass the 1 to the callback, in InDesign the callback will be triggered but the 1 will not be received In Script 2 even InDesign will will pass the 1 to the callback because it was explicitly passed as a string. Setting the forceEval to true will wrap the script in an eval and therefore force the result to be a String
Summary: Don't set forceEval to true unless you are 1) Using InDesign and 2) You need the result.

Setting up the extension with JSX.js
How does one set up the extension so that one can restart the extension at a click of a button and all the changes in both the js and jsx files will be reflected?

Include in the index.html file the following line (or something similarish) to add the button. When the scripts development is done you can remove the line.

Include the following files. If you prefer you can use plain js instead of jQuery. ../js/buttons.js is the name I give the js script for controlling th HTML UI, substitute with the name you use.

In your main.js file you execute your host.jsx file
In your buttons.js (or whatever you call your file that deals with your UI functions) file include something like this.
Then when you click on your button the extension will restart including all the jsx files, slashing development time
See the annotation at the beginning of the script for cost and terms of use.
JSX.js (Download) 💾

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

Please show you are a human. Time limit is exhausted. Please reload CAPTCHA.