Skip to main content
Elwissan
Inspiring
February 28, 2023
Answered

How to save and later load plugin options in Illustrator? [Illustrator CC 2022, 2023, JS JSX]

  • February 28, 2023
  • 1 reply
  • 1265 views

Hi,

I'm developing a Plugin. In the main.js file, how do I save and then load the plug-in options in Illustrator?

 

The way below only works in jsx file:
app.preferences.setStringPreference('mySettings', mytext);
var loadSettings = app.preferences.getStringPreference('mySettings');

 

The problem is when you run csInterface to run the jsx and load the settings saved in Illustrator: "csInterface.evalScript(FunctionJSX)..." is executed before another function, but this function is executed first... waiting for the values. The plug-in loads without options saved.

 

Thanks!

This topic has been closed for replies.
Correct answer Manan Joshi

Hi @Elwissan,

The code was doing exactly as you told it to do. Your solution is also correct. However, as you asked for a better way to solve this I think you are not very clear on why it behaved the way it did and how this was solved. Let me take a stab at explaining what is going on here.

You intial code can be summarized as doing the following things

  • Variable decleration, objData
  • Function decleration, ObjSize
  • Calling the extendscript method, with an event handler added to it which is executed on getting a response from the extendscript method
  • Calling the ObjSize method

Now do note that JS is async in nature. Which means that the thread does not block over an operation but moves ahead after calling a function. The exact same thing happens in your code as well. It calls the extendscript method and registers a callback to be called once the method execution is done and moves ahead. The next statement is the call to ObjSize method and you might be seeing that being executed before the response callback of the extendscript method. In order to avoid this situation it's always prudent to add in code in the callback to guarantee their calling sequence. When you call ObjSize from with the response callback you are explicitly saying execute the extendscript method and when it's done then call the ObjSize method.

Also a slight improvement to your solution would be to avoid code duplication and just call the method ObjSize from within the callback

 

// initial values
var objData = {
    width: 0,
    height: 0,
    check: false,
};

function ObjSize() {
    if (objData.check) {
        document.getElementById('Width_input').value = objData.width;
        document.getElementById('Height_input').value = objData.height;
    }
    else {
        document.getElementById('Width_input').value = 20; // default value
        document.getElementById('Height_input').value = 10; // default value
    }
}

csInterface.evalScript('myLoad_Settings(' + JSON.stringify(objData) + ')', function (response) {
    var result = JSON.parse(response);
    objData.width = result.width;
    objData.height = result.height;
    objData.check = result.check; // true or false
    ObjSize();
});

 

I hope this makes better sense to you now. In order to understand this more clearly I would recommend you study the following things

  • Async code execution/ event loops
  • Callbacks
  • Promises

-Manan

1 reply

Community Expert
March 1, 2023

Can you share more details, probably a bit more of the code could help. At what point do you want to save the settings exactly and when do you intend to read it back?

-Manan

-Manan
Elwissan
ElwissanAuthor
Inspiring
March 2, 2023

Hi Manan Joshi

 

The ObjSize() function has to be executed after csInterface.evalScript(...), but it was being executed before:
// initial values
var objData = {
    width: 0,
    height: 0,
    check: false,
};

function ObjSize() {
    if (objData.check) {
        document.getElementById('Width_input').value = objData.width;
        document.getElementById('Height_input').value = objData.height;
    }
    else {
        document.getElementById('Width_input').value = 20; // default value
        document.getElementById('Height_input').value = 10; // default value
    }
}

csInterface.evalScript('myLoad_Settings(' + JSON.stringify(objData) + ')', function (response) {
    var result = JSON.parse(response);
    objData.width = result.width;
    objData.height = result.height;
    objData.check = result.check; // true or false
});
ObjSize();

 

I managed to solve it this way:
I copied the contents of the ObjSize() function into csInterface.evalScript(...)
csInterface.evalScript('myLoad_Settings(' + JSON.stringify(objData) + ')', function (response) {
    var result = JSON.parse(response);
    objData.width = result.width;
    objData.height = result.height;
    objData.check = result.check;
    if (result.check) {
        document.getElementById('Width_input').value = objData.width;
        document.getElementById('Height_input').value = objData.height;
    }
    else {
        document.getElementById('Width_input').value = 20; // default value
        document.getElementById('Height_input').value = 10; // default value
    }
});

 

The ObjSize() function continued to exist for other commands.
The codes were duplicated, but it solved my problem.

Now I can use the .jsx file without any problems.

 

If there is a better option. Please post.

Thanks

Manan JoshiCommunity ExpertCorrect answer
Community Expert
March 5, 2023

Hi @Elwissan,

The code was doing exactly as you told it to do. Your solution is also correct. However, as you asked for a better way to solve this I think you are not very clear on why it behaved the way it did and how this was solved. Let me take a stab at explaining what is going on here.

You intial code can be summarized as doing the following things

  • Variable decleration, objData
  • Function decleration, ObjSize
  • Calling the extendscript method, with an event handler added to it which is executed on getting a response from the extendscript method
  • Calling the ObjSize method

Now do note that JS is async in nature. Which means that the thread does not block over an operation but moves ahead after calling a function. The exact same thing happens in your code as well. It calls the extendscript method and registers a callback to be called once the method execution is done and moves ahead. The next statement is the call to ObjSize method and you might be seeing that being executed before the response callback of the extendscript method. In order to avoid this situation it's always prudent to add in code in the callback to guarantee their calling sequence. When you call ObjSize from with the response callback you are explicitly saying execute the extendscript method and when it's done then call the ObjSize method.

Also a slight improvement to your solution would be to avoid code duplication and just call the method ObjSize from within the callback

 

// initial values
var objData = {
    width: 0,
    height: 0,
    check: false,
};

function ObjSize() {
    if (objData.check) {
        document.getElementById('Width_input').value = objData.width;
        document.getElementById('Height_input').value = objData.height;
    }
    else {
        document.getElementById('Width_input').value = 20; // default value
        document.getElementById('Height_input').value = 10; // default value
    }
}

csInterface.evalScript('myLoad_Settings(' + JSON.stringify(objData) + ')', function (response) {
    var result = JSON.parse(response);
    objData.width = result.width;
    objData.height = result.height;
    objData.check = result.check; // true or false
    ObjSize();
});

 

I hope this makes better sense to you now. In order to understand this more clearly I would recommend you study the following things

  • Async code execution/ event loops
  • Callbacks
  • Promises

-Manan

-Manan