Copy link to clipboard
Copied
Imagine you have files
In "main.jsx" you specify #target, #targetengine directives so some of your variables could be persistent and use #include to get your utils functions so you could use them later.
And... Here you go, your values are not persistent. They become persistent only if you get rid of #include statement. Is it intended behaviour? How do i make #targetengine work and keep my variables at next script run with #include directive? Unfortunately i can't serialize my values to string and save it later so session is my only option.
Example code below:
--- main.jsx ---
#target illustrator
#targetengine "session001"
#include 'utils.jsx';
if (isNaN(foo)) var foo = 0;
foo += 2;
alert(foo);
--- utils.jsx ---
var bar = null;
Hi @some_5675, DOM reference in Illustrator are fragile, so I wouldn't waste any time trying to keep one. They are broken by many common actions, such as closing/re-opening the document, or simply adding or removing a page item "before" the reference page item (altering the DOM "after" the page item should be fine).
One of your problems is the speed to retrieve your page items graph. Have you tried using
var myItem = doc.getPageItemFromUuid(myPageItemID);
exclusively to create your graph? Is
...Copy link to clipboard
Copied
It seems `targetengine` may not be supported in newer versions of Ai (docs), but I've never used that directive so I don't know for sure (docs just may be old). It is hard to tell what you are trying to accomplish with your code but if you need something to persist you could always write it to a file (and read it later) or use `$.setenv()` and `$.getenv()`. I use both options a lot with "include" files and it works great.
Copy link to clipboard
Copied
Thank you for the reply. It's a pitty if it not works that way.
It is hard to tell what you are trying to accomplish with your code
I have graph-like structure inside SVG. Each item is a native PathItem object. I parse all objects from layer and build graph structure to manipulate it later but it builds everytime i run the script and could take a while. I want to keep the data i parsed last time.
I tried to use json2 library but it refuses to serialize my object (probably because it has PathItem objects inside and they are not serializable) and script fails without an error. So i need a way to somehow keep my data persistent.
Copy link to clipboard
Copied
You can save "JSON-like" data to a file and read it back using `eval()` (docs) without an external library.
Copy link to clipboard
Copied
Thanks, will check it closer. But i think it obviously will not keep reference of PathItem for me so i won't be able to manipulate with certain item like change it's color and i'll need to parse all references again, right?
Copy link to clipboard
Copied
Yep, you could give the items a tag or see if they have a uuid already assigned, then use those as a reference.
Copy link to clipboard
Copied
Also forgot to mention that if i serialize data to string i will definitely will loose PathItem reference on retrieving so i will need to acquire/parse it again. So session and keeping runtime variables is my best option.
Copy link to clipboard
Copied
Sorry, just saw this after posting my other comment. Yeah, you will not be able to serialize a built-in PathItem to my knowledge. Maybe you could take just the info you need from the path item (like point data) and serialize that for later manipulation.
Copy link to clipboard
Copied
Hi @some_5675, DOM reference in Illustrator are fragile, so I wouldn't waste any time trying to keep one. They are broken by many common actions, such as closing/re-opening the document, or simply adding or removing a page item "before" the reference page item (altering the DOM "after" the page item should be fine).
One of your problems is the speed to retrieve your page items graph. Have you tried using
var myItem = doc.getPageItemFromUuid(myPageItemID);
exclusively to create your graph? Is it too slow?
- Mark
P.S. As you noticed the JSON library cannot stringify DOM items. This is for two immediate reasons: (1) they contain cyclic structures that would cause JSON.stringify to loop forever if not aborted, eg. there are properties that return a parent object, which itself has properties that return the original child object, and (2) Illustrator crashes when trying to read some properties of some DOM items! Not to mention that you really don't want to serialize the entire thing—it can be quite long and slow process.
The usual approach is to provide JSON.stringify with a `replacer` function (and JSON.parse with a `reviver` function, if necessary). Here is a little example of a replacer for stringifying a PathItem:
/**
* Example replacer for PathItem
* @param {String|Number} [key] - the access key (default: undefined).
* @param {*} value - the value to replace.
* @returns {*?} - the value to serialize.
*/
function pathItemReplacer(key, value) {
// unfortunately we have to try/catch here
// because some DOM objects throw weird errors
// for no good reasons
try {
if ('parent' === key)
// parent objects usually cause cyclic structure
// and we don't want them anyway
return undefined;
if ('Number' === key.constructor.name)
// don't interfere with normal array access
return value;
if (
'PathItem' === value.typename
|| 'PathPoint' === value.typename
)
// send this back for further serialising
return value;
switch (key) {
case 'uuid':
case 'anchor':
case 'leftDirection':
case 'rightDirection':
// JSON can stringify these
return value;
case 'note':
// only if exists
return '' !== value ? value : undefined;
case 'pointType':
// special handling
return String(value);
case 'pathPoints':
// JSON can't always handle "collections"
// so return a normal Array
var pathPoints = [];
for (var i = 0; i < value.length; i++)
pathPoints[i] = value[i];
return pathPoints;
case 'fillColor':
case 'strokeColor':
// just for an example, we'll
// only stringify a swatch name
if (
value
&& value.typename
&& 'SpotColor' === value.typename
)
return value.spot.name;
default:
// ignore everything else
return undefined;
};
}
catch (error) {
// we definitely don't want anything that throws errors!
return undefined;
}
};
Copy link to clipboard
Copied
Much thanks for the clear answer. In the end i implemented script i need without keeping record of last graph structure and time it need to initialize is not hardcore and by far i can live with it.
Was not aware about 'getPageItemFromUuid'. Next time if i found myself in a performance issue i definitely will try it or the replacer function you suggested. Thanks.
Copy link to clipboard
Copied
Also some operations are very slow for no good reason, eg.
myPageItem.selected = true
So it is better to avoid selecting items individually and instead do, eg.
myDoc.selection = myArrayOfItems;