Home > InDesign Scripts > Saving Script Data using JSON [Part 2]

Saving Script Data using JSON [Part 2]

When building complex scripts with lot of options that user can choose, it’s always great to allow user to also save selected settings and reuse them on next launch. We already discussed about this topic in earlier post [Saving script data within document] but I recently found better way for serializing and storing data.

In first post, I used simple “*” to separate multiple values, and at load time used split(*) to separate values back to Array. That’s not bad, and it’s working fine, but there is another much more elegant solution!

What is JSON? JSON (JavaScript Object Notation) is a lightweight data-interchange format in other words it’s Associative array. It is, among other things, a faster, simpler, easier-to-use alternative to XML. More info about JSON can be found here: Introducing JSON. That’s great, but how to use it in InDesign?! How to save/load values?

I created short sample to demonstrate usage and shortly explain how it works. Of course, you can extend it as you wish! So, let’s get started! :D


First, let’s take a look at simple JSON (Associative array) object:

var myJSON = { myText: "My First Text", myValue: 1 };

// displaying values
alert(myJSON.myText); // My First Text
alert(myJSON.myValue); // 1

So, the main idea is to populate simply populate JSON object with dialog values and save them into app or document label. But, label is String value, and JSON is object, so before saving we need to convert JSON to string. Easiest way to do that is to use toSource() which will generate String from JSON object.

alert(myJSON.toSource()); // ({myText:"My First Text", myValue:1})

Another great thing is that we don’t have to think about escaping reserved characters, they are automatically escaped during conversion to string!

So, let’s build really simple example! First we need simple dialog. As you see on image, it will contain three text boxes, two check boxes and one dropdown:

// loading saved settings
var loadSettings = eval(app.activeDocument.extractLabel("mySettings"));

// function which assigns values to elements
var myValues = function(setObj, defValue){
    if(loadSettings != undefined){
        if(loadSettings[setObj]){
            return loadSettings[setObj];
        }
    }else{
        return defValue;
    }
};

// array for dropdown element
var myArray = ["Level 1", "Level 2", "Level 3", "Level 4", "Level 5"];

// dialog
var myWin = new Window('dialog', "Save Settings / by IndiSnip");

// elements
var myT1 = myWin.add('edittext', undefined, myValues("myT1", "Name"));
    myT1.characters = 20;
var myT2 = myWin.add('edittext', undefined, myValues("myT2", "Company"));
    myT2.characters = 20;
var myT3 = myWin.add('edittext', undefined, myValues("myT3", "E-mail"));
    myT3.characters = 20;
var myC1 = myWin.add('checkbox', undefined, "Newsletter");
    myC1.value = myValues("myC1", true);
var myC2 = myWin.add('checkbox', undefined, "Support");
    myC2.value = myValues("myC2", false);
var myD1 = myWin.add('dropdownlist', undefined, myArray);
    myD1.selection = myValues("myD1", 0);
var myOK = myWin.add('button', undefined, "OK");

// this is more like bonus element
// which enables you to reset values to default
var myReset = myWin.add('button', undefined, "Reset");
    myReset.onClick = function(){myWin.close(3);};
    loadSettings != undefined ? myReset.enabled = true : myReset.enabled = false;

// center dialog [optional]
myWin.center();

// show dialog
var myRes = myWin.show();

// switch dialog close value
if(myRes == 1){ // OK is clicked
    var mySettings = {}; // new JSON
    // adds values from dialog to JSON
    mySettings['myT1'] = myT1.text;
    mySettings['myT2'] = myT2.text;
    mySettings['myT3'] = myT3.text;
    mySettings['myC1'] = myC1.value;
    mySettings['myC2'] = myC2.value;
    mySettings['myD1'] = myD1.selection.index;
    // saves JSON which is converted to string to activeDocument label
    app.activeDocument.insertLabel("mySettings", mySettings.toSource());
}else if(myRes == 3){ // Reset is clicked
    // clears activeDocument label
    app.activeDocument.insertLabel("mySettings", "");
}

OK, let’s explain this a little bit :) Key part is in myValues(setObj, defValue) function which loads saved data if any, or assigns default data if no data stored. Keep in mind that setObj has to be the same when saving data (line 52), if not, data will not match! String which is loaded from label has to be converted to JSON object using eval() to make it accessible!

Here you can see how JSON from example above looks like when filled with data and converted to String:

And here is dialog which is loaded with already saved data:

Maybe you can make this more efficient if you build your own ScriptUI widgets. You can implement this technique directly into widgets and add more control over content/values of your dialog elements.

That’s it!

Happy coding! :D

About these ads
  1. carlo
    March 14, 2011 at 23:10

    very interesting!
    just a typo:

    60 }else if(myRes == 3 // Reset is clicked
    61 // clears activeDocument label
    62 app.activeDocument.insertLabel(“mySettings”, “”);
    63 }

    should be:

    60 }else if(myRes == 3){ // Reset is clicked
    61 // clears activeDocument label
    62 app.activeDocument.insertLabel(“mySettings”, “”);
    63 }

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 34 other followers

%d bloggers like this: