6 Replies Latest reply on May 28, 2008 10:18 AM by (Olav_Kvern)

    [JS/AS] Storing values that persist between runs of scripts

      I have written a number of Applescripts that use Applescript Properties to to store the values chosen by users in dialog boxes etc between successive runs of the script (in AS they persist until the script is recomplied).

      I am investigating converting these scripts to JS to enable them to be used cross platform, and am slowly bringing myself up to speed with JS. However, I cannot see any obvious equivalent to AS properties.

      Does any one have any advice on how they store user defaults, preferences etc between script runs. Any code fragments would be appreciated.

      Many thanks, Nye
        • 1. Re: [JS/AS] Storing values that persist between runs of scripts
          Kasyan Servetsky Level 5
          Hi Nye,

          I have an example script, posted by Olav Kvern in June 2007, the topic was called [CS3:JavaScript] Saving Dialog Settings and it is not on forum any more. If you need it I can send it to you, or repost it.

          Kasyan
          • 2. Re: [JS/AS] Storing values that persist between runs of scripts
            Level 1
            Hello Kasyan,

            That would be very useful. I think a repost would be of the most use to the other forum readers.

            Many thanks, Nye
            • 3. Re: [JS/AS] Storing values that persist between runs of scripts
              Kasyan Servetsky Level 5
              //NeonWithPrefs.jsx
              
              //An InDesign CS3 JavaScript
              //
              //This script creates a "blend" or "graduation" from the selected object or objects.
              //
              //For more on InDesign scripting, go to http://www.adobe.com/products/indesign/scripting.html
              //or visit the InDesign Scripting User to User forum at http://www.adobeforums.com
              //
              main();
              function main(){
              var myObjectList = new Array;
              if (app.documents.length != 0){
                if (app.selection.length != 0){
                 for(var myCounter = 0;myCounter < app.selection.length; myCounter++){
                  switch (app.selection[myCounter].constructor.name){
                   case "Rectangle":
                   case "Oval":
                   case "Polygon":
                   case "GraphicLine":
                    myObjectList.push(app.selection[myCounter]);
                   break;
                  }
                 }
                 if (myObjectList.length != 0){
                  myDisplayDialog(myObjectList);
                 }
                 else{
                  alert ("Please select a rectangle, oval, polygon, or graphic line and try again.");
                 }
                }
                else{
                 alert ("Please select an object and try again.");
                }
              }
              else{
                alert ("Please open a document, select an object, and try again.");
              }
              }
              function myDisplayDialog(myObjectList){
              var mySwatchNamesList = new Array;
              var myLayerNamesList = app.documents.item(0).layers.everyItem().name;
              for(var myCounter = 0;myCounter < app.activeDocument.colors.length; myCounter ++){
                //Do not add(); unnamed colors.
                if(app.activeDocument.colors.item(myCounter).name != ""){
                 mySwatchNamesList.push(app.activeDocument.colors.item(myCounter).name);
                }
              }
              for(var myCounter = 0;myCounter < app.activeDocument.mixedInks.length; myCounter ++){
                mySwatchNamesList.push(app.activeDocument.mixedInks.item(myCounter).name);
              }
              //New stuff for setting dialog box controls to the last-selected options.
              //
              //While the basic XML preferences-reading mechanisms are generic,
              //significant handling has to be done by the dialog box to read and
              //use the stored values.
              //
              //List of dialog box parameters for Neon.jsx:
              //NumberOfSteps--integer
              //FromStrokeColor--string
              //FromStrokeWeight--double
              //ToStrokeWeight--double
              //FromStrokeTint--percent
              //ToStrokeTint--percent
              //LayerName--string
              //
              var myParameterArray = myGetDialogPreferences("NeonWithPrefs", ["NumberOfSteps", "FromStrokeColor", "FromStrokeWeight", "ToStrokeWeight", "FromStrokeTint", "ToStrokeTint", "LayerName"]);
              //myPreferences is the XML object that should lead off the array.
              var myPreferences = myParameterArray[0];
              try{
                if(myParameterArray.length == 8){
                 //If any of these conversions fails, we'll set the
                 //values back to the defaults by handling the error.
                 myNumberOfSteps = parseInt(myParameterArray[1]);
                 if(myNumberOfSteps <=1){
                  throw "Too few steps.";
                 }
                 myFromStrokeColor = myParameterArray[2];
                 myFromStrokeWeight = parseFloat(myParameterArray[3]);
                 myToStrokeWeight = parseFloat(myParameterArray[4]);
                 myFromStrokeTint = parseFloat(myParameterArray[5]);
                 myToStrokeTint = parseFloat(myParameterArray[6]);
                 myLayerName = myParameterArray[7];
                }
                else{
                 throw "Could not read from preferences file.";
                }
              }
              catch(myError){
                //Default values.
                myNumberOfSteps = 12;
                myFromStrokeColorName = "Black";
                myFromStrokeWeight =12;
                myToStrokeWeight = .25;
                myFromStrokeTint = 100;
                myToStrokeTint = 10;
                myLayerName = "Layer 1"; 
              }
              //Now process the stroke color index.
              myFromStrokeColorIndex = myGetIndex(mySwatchNamesList, myFromStrokeColor);
              //Now process the layer index.
              myLayerIndex = myGetIndex(myLayerNamesList, myLayerName);
              //End of preference-gathering stuff.
              var myDialog = app.dialogs.add({name:"Neon"});
              with(myDialog){
                with(dialogColumns.add()){
                 with(borderPanels.add()){
                  with(dialogColumns.add()){
                   staticTexts.add({staticLabel:"Number of Steps:"});
                  }
                  with(dialogColumns.add()){
                   //Updated.
                   var myNumberOfStepsField = integerEditboxes.add({editValue:myNumberOfSteps});
                  }
                 }
                 with(borderPanels.add()){
                  with(dialogColumns.add()){
                   staticTexts.add({staticLabel:"From:", minWidth:36});
                  }
                  with(dialogColumns.add()){
                   with(dialogRows.add()){
                    with(dialogColumns.add()){
                     staticTexts.add({staticLabel:"Stroke Color:", minWidth:100});
                    }
                    with(dialogColumns.add()){
                     //Updated, var name mySwatchIndex.
                     var myFromStrokeColorMenu = dropdowns.add({stringList:mySwatchNamesList, selectedIndex:myFromStrokeColorIndex});
                    }
                   }
                   with(dialogRows.add()){
                    with(dialogColumns.add()){
                     staticTexts.add({staticLabel:"Stroke Weight:", minWidth:100});
                    }
                    with(dialogColumns.add()){
                     //Updated.
                     var myFromStrokeWeightField = realEditboxes.add({editValue:myFromStrokeWeight});
                    }
                   }
                   with(dialogRows.add()){
                    with(dialogColumns.add()){
                     staticTexts.add({staticLabel:"Stroke Tint:", minWidth:100});
                    }
                    with(dialogColumns.add()){
                     //Updated.
                     var myFromStrokeTintField = percentEditboxes.add({editValue:myFromStrokeTint});
                    }
                   }
                  }
                 }
                 with(borderPanels.add()){
                  with(dialogColumns.add()){
                   staticTexts.add({staticLabel:"To:", minWidth:36});
                  }
                  with(dialogColumns.add()){
                   with(dialogRows.add()){
                    with(dialogColumns.add()){
                     staticTexts.add({staticLabel:"Stroke Weight:", minWidth:100});
                    }
                    with(dialogColumns.add()){
                     //Updated.
                     var myToStrokeWeightField = realEditboxes.add({editValue:myToStrokeWeight});
                                   }
                   }
                   with(dialogRows.add()){
                    with(dialogColumns.add()){
                     staticTexts.add({staticLabel:"Stroke Tint:", minWidth:100});

                    }
                    with(dialogColumns.add()){
                     //Updated.
                     var myToStrokeTintField = percentEditboxes.add({editValue:myToStrokeTint});
                    }
                   }
                  }
                 }
                 with(borderPanels.add()){
                  with(dialogColumns.add()){
                   staticTexts.add({staticLabel:"Destination Layer:"});
                  }
                  with(dialogColumns.add()){
                   //Updated.
                   var myLayersMenu = dropdowns.add({stringList:myLayerNamesList, selectedIndex:myLayerIndex});
                  }
                 }
                }
              }
              var myResult = myDialog.show();
              if(myResult == true){
                //Get the values from the dialog box controls
                var myNumberOfSteps = myNumberOfStepsField.editValue;
                var myFromStrokeColor = mySwatchNamesList[myFromStrokeColorMenu.selectedIndex];
                var myFromStrokeWeight = myFromStrokeWeightField.editValue;
                var myToStrokeWeight = myToStrokeWeightField.editValue;
                var myFromStrokeTint = myFromStrokeTintField.editValue;
                var myToStrokeTint = myToStrokeTintField.editValue;
                var myLayerName = myLayerNamesList[myLayersMenu.selectedIndex];
                myDialog.destroy();
                //Write dialog preferences file.
                //Change the values in the XML preferences object.
                myPreferences.NumberOfSteps = myNumberOfSteps;
                myPreferences.FromStrokeColor = myFromStrokeColor;
                myPreferences.FromStrokeWeight = myFromStrokeWeight;
                myPreferences.ToStrokeWeight = myToStrokeWeight;
                myPreferences.FromStrokeTint = myFromStrokeTint;
                myPreferences.ToStrokeTint = myToStrokeTint;
                myPreferences.LayerName = myLayerName;
                //Write the values back to the XML file.
                myWriteXMLPreferences("NeonWithPrefs", myPreferences);
                //Apply the effect.
                myNeon(myObjectList, myNumberOfSteps, myFromStrokeColor, myFromStrokeWeight, myToStrokeWeight, myFromStrokeTint, myToStrokeTint, myLayerName);
              }
              else{
                myDialog.destroy();
              }
              }
              function myNeon(myObjectList, myNumberOfSteps, myFromStrokeColor, myFromStr
              • 4. Re: [JS/AS] Storing values that persist between runs of scripts
                Level 1
                Oh good, I found the Olav Kvern topic in the archive at:
                http://www.adobeforums.com/cgi-bin/webx/.3bc44567/0

                Thanks for the tip Kasyan, that looks like just what i need. (Much simpler in AS though!)
                • 5. Re: [JS/AS] Storing values that persist between runs of scripts
                  Kasyan Servetsky Level 5
                  That's good - I failed to repost entire script - it's too big.
                  • 6. Re: [JS/AS] Storing values that persist between runs of scripts
                    Level 1
                    Nye Hughes wrote: "(Much simpler in AS though!)"

                    Note that only a relatively small part of the script in the post is doing the reading/writing of XML preferences from the disk. If you didn't want to do that, you could always store the values in a a persistent JavaScript engine (such as "session").

                    It might be simpler to store such values as script properties in AppleScript, but a.) you need to save the script as a compiled script (something that always seems to cause problems), and b.) if you try reading and writing XML in AppleScript without using the Late Night XML extensions, you'll probably need something at least as long.

                    I don't have anything against AppleScript, by the way--I just wanted to point out that you're comparing apples (so to speak) and oranges.:-)

                    Thanks,

                    Ole