14 Replies Latest reply on Dec 29, 2011 11:12 AM by Gordon The Scripter

    How to change the "TextVariable" via javascript

    Gordon The Scripter

      Hi,

       

      How do I change the value of a "Custom Text Variable" via javascript in indesign CS5?

       

      I understand that there is a "contents" property available to me but I can't figure out how to set or change it.

       

      Below is javascript code for example reference.

       

      var docRef = app.activeDocument;
      
      
      for ( var i = 0; i < docRef.textVariables.length; i++ ) {
      
      
          var textVariableItem = docRef.textVariables[i];
      
      
                // Check for the type
                if (textVariableItem.variableType === VariableTypes.CUSTOM_TEXT_TYPE){
      
      
                          var variableOption = textVariableItem.variableOptions;
        
                          // This will give me the text value of the variable
                          alert("Text Variable " + i + " \n " + textVariableItem.name + "\n" + variableOption.contents);
      
      
                          // But how do I set it? 
                          // The following does not seem to work 
                          variableOption.contents = "New custom text..."; 
                }
      }
      
        • 1. Re: How to change the "TextVariable" via javascript
          Green4ever Level 3

                              // But how do I set it?
                              // The following does not seem to work
                              variableOption.contents = "New custom text...";

          try the below line,

           

          textVariableItem.variableOptions.contents = "New custom text...";

           

          I guess you are changing the reference not the original item..

           

          Green4ever

          • 2. Re: How to change the "TextVariable" via javascript
            Harbs. Level 6

            I ran your code and it works perfectly fine for me.

             

            Are you sure you're looking at the text? It only changes the text applied in InDesign, not the name as it appears in the variable list.

             

            Harbs

            • 3. Re: How to change the "TextVariable" via javascript
              Gordon The Scripter Level 1

              Harbs

               

              It does not work for me. Notice what happens when you run this block of code.

               

              The second alert never gets called. Either way I am still confused on how to change the value of contents of a custom text variable via script.

               

               

               

              var docRef = app.activeDocument;

               

                

              for ( var i = 0; i < docRef.textVariables.length; i++ ) {

               

               

                  var textVariableItem = docRef.textVariables[i];

               

               

                        // Check for the type

                        if (textVariableItem.variableType === VariableTypes.CUSTOM_TEXT_TYPE){

               

               

                                  var variableOption = textVariableItem.variableOptions;

               

               

                                  // This will give me the text value of the variable

                                  alert("Text Variable BEFORE " + i + " \n " + textVariableItem.name + "\n" + variableOption.contents);

               

                

                                  // But how do I set it?

                                  // The following does not seem to work

                                                                textVariableItem.variableOptions.contents = "New custom text...";

               

               

                                                                // This does not get called the script fails somewhere executing the above line

                                  alert("Text Variable AFTER " + i + " \n " + textVariableItem.name + "\n" + variableOption.contents);

               

               

                        }

              }

               

              For clarification here is how I have my document setup. A very basic example a single page with a text frame and a custom text variable with the value of
              "Foo".

               

              Screen Shot 2011-12-23 at 11.06.01 AM.png

               

               

              And this is what I get when I run the script. I can obviously get the value of the variable but I cannot change it. My text frame stil says "Foo" after the script runs.

               

              Screen Shot 2011-12-23 at 11.05.32 AM.png

              • 4. Re: How to change the "TextVariable" via javascript
                Harbs. Level 6

                I tried in both CS5 and CS5.5 and it works in both.

                2011-12-25_1043.png

                2011-12-25_1043_1.png

                Something is probably wonky on your system. Try trashing your prefs...

                 

                Harbs

                • 5. Re: How to change the "TextVariable" via javascript
                  [Jongware] Most Valuable Participant

                  I agree with Harbs. I ran your code and it totally works as expected. Adding two Custom Text variables shows the first one changing, then the second one, both to the new text.

                  • 6. Re: How to change the "TextVariable" via javascript
                    Green4ever Level 3

                    The same code works well. As said by Harbs, try clearing your preferences and then check again.

                    • 7. Re: How to change the "TextVariable" via javascript
                      Gordon The Scripter Level 1

                      Thanks to everyone who responded. I tested this a little further. I had some javascript wrapper code around this functionality that was causing the issue. I had some boilerplate code that was used for creating a script UI dialog interface and this code was inside a callback function. I think was running into scope issues or a undefined variable somewhere.

                       

                      Anyway, seems to be working for me now.

                       

                      Thanks,

                      Gordon

                      • 8. Re: How to change the "TextVariable" via javascript
                        Gordon The Scripter Level 1

                        Harbs, et. al.

                         

                        OK I have isolated the script to reproduce and hopefully illustrate the problem I am having.

                         

                        The script does not get to the end of a function I have called "doAction" and I am not certain why. There is a lot going on in the script including some script UI stuff and the generation of dialog boxes. I would be happy to explain the thinking behind it. I was hoping that perhaps someone might point out the obvious flaws. If you run it hopefully you can see what I am try to do with dialog boxes. But if there is a best practice on how to setup a script like this please let me know.

                         

                        This code DOES NOT work (the more complex case with dialog boxes etc)

                        https://gist.github.com/1530581

                         

                        The code seems to fail around line 230

                         

                         

                        This code DOES work (the simple case)

                        https://gist.github.com/1530777

                         

                        Tips? Suggestions? I am probably overlooking something basic.

                         

                        Thanks,

                        Gordon

                        • 9. Re: How to change the "TextVariable" via javascript
                          Gordon The Scripter Level 1

                          OK, getting a little closer.

                           

                          In the extendscript toolkit I am seeing the following error:

                           

                          "Cannot handle the request because a modal dialog or alert is active".

                           

                          The problem must be because of the tricky way in which I have my dialog box callback function working in my script. Anybody, have a good example of doing a script UI dialog box and passing parameters back out to a callback function?

                           

                          I suspect the way I have this setup is not going to work in the context I need it to. Funny it seems to work just fine in illustrator CS5.

                           

                          Gordon

                          • 10. Re: How to change the "TextVariable" via javascript
                            Green4ever Level 3

                            Ha ha... I found the solution but you have code it.

                            The dialog is actually not closed. set name of the continue button to "ok".

                            and the calling function should not be inside the "sfDialogFactory" function.

                             

                            In dialogs if ok button is pressed it will return value 1. Using that value call the outside function (ie: call back function).

                            example:

                            if (myDialog.show() == 1){

                                 //call your function

                                 }

                            Give it a try....

                             

                            Thanks,

                            Green4ever

                            • 11. Re: How to change the "TextVariable" via javascript
                              Gordon The Scripter Level 1

                              Green4ever,

                               

                              I think I get what you are saying but I am still a little hazy on the where to place the callback. Doing proper click handler functions for the OK/Cancel buttons within a dialog box and still passing along parameters with that event is still not completely crystal clear to me. I realize maybe my by going through the sfDialogFactory function I am creating issues,

                               

                              I have updated the script to what I think you are suggesting:

                               

                              https://gist.github.com/1530581

                               

                              However, it doesn't quite work. And also, I seem still to be getting a return value of 0 from the call to

                               

                              myDialog.show()

                               

                              I am still doing something wrong. If it is convenient, could you just edit the above gist to illustrate what you mean? Or perhaps you have a very simple example of a dialog that has a click button handler and is passing dialog parameters through the event handler into another function. Maybe my solution is still a hack.

                               

                              Thanks,

                              Gordon

                              • 12. Re: How to change the "TextVariable" via javascript
                                Green4ever Level 3

                                I'll try to edit your code little later. For now you try this method to close the dialog window. It may help you

                                bOK.onClick = function(){

                                          formData = getControlValues(inputGroup);

                                          // dialog.callback("continue", formData);

                                          d.close(1);

                                      };

                                Thanks,

                                Green4ever

                                • 13. Re: How to change the "TextVariable" via javascript
                                  Green4ever Level 3
                                  // Logic behind this script
                                  
                                  // theScript()
                                  // is a wrapper function to provide functional scope to the entire script
                                  // This function is invoked at the very bottom of the file
                                  
                                  // main();
                                  // the main function that gathers the initial parameters and launches the dialog box
                                  
                                  // function mainDialog(docRef, selectedItems, layers, inputs)
                                  // A function that creates a dialog box this function is passed as a parameter to a "factory method"
                                  // called function sfDialogFactory(dialog)
                                  // which is a general purpose utility for creating dialog boxes.
                                  
                                  // The mainDialog function has a callback function that responds to the "comtinue" button and after some validation
                                  // makes a call to a function called
                                  
                                  // function doAction(docRef, inputs, options)
                                  // This is where the main behvior of the script is suppose to be defined.
                                  // it is designed to be called AFTER the dialog box return and is the result of the callback inside mainDialog
                                  // The doAction function receives objects that are parameter holders for various inputs and options that come from the
                                  // dialog box presented to the user
                                  
                                  
                                  
                                  function theScript() {
                                  ///////////////////////////////////////////////////
                                  // BEGIN THE SCRIPT
                                  //=================================================
                                  
                                  
                                  ////////////////////////////////////////////////////////////////////////////////
                                  // SCRIPT MAIN PROCESS
                                  ////////////////////////////////////////////////////////////////////////////////
                                  // Main Process
                                  // The beginning of the script starts here
                                  // Add main logic routine to this function
                                  
                                  // Call Main Function to get the ball rolling
                                  var elementsData;
                                  var theDocument = app.activeDocument;
                                  var inputGroup;
                                  main();
                                  
                                  function main(){
                                  var theSelectedItems = theDocument.selection;
                                  var theLayers = theDocument.layers;
                                  
                                      var myDialog = sfDialogFactory(mainDialog(theDocument, theSelectedItems), theLayers);
                                      var result = myDialog.show();
                                      if (result == 1){
                                          newAction();
                                          alert("Done");
                                          }
                                      else{
                                          alert("Not Done");
                                          }
                                  }
                                  
                                  ////////////////////////////////////////////////////////////////////////////////
                                  // SCRIPT SUPPORTING FUNCTIONS
                                  ////////////////////////////////////////////////////////////////////////////////
                                  // Supporting Functions
                                  // Include functions that offer partial functionality
                                  // These functions are called and acted upon within the mainProcess function
                                  function newAction(){
                                          
                                          var formData = getControlValues(inputGroup);    
                                          var inputs = {};
                                          var options = {};
                                         // alert("callback get form data");
                                        // Do something with formData values here
                                          var cLen = formData.controls.length;
                                          var formValues = '';
                                          for (var c = 0; c < cLen; c++ )
                                          {
                                              if (formData.controls[c].name === "inputECONumber") {
                                                  inputs.inputECONumber = formData.controls[c].value;
                                                  // alert(formData.controls[c].name + " | " + formData.controls[c].value);
                                              }
                                  
                                              if (formData.controls[c].name === "inputDocumentName") {
                                                  inputs.inputDocumentName = formData.controls[c].value;
                                                  // alert(formData.controls[c].name + " | " + formData.controls[c].value);
                                              }
                                  
                                              if (formData.controls[c].name === "inputDocumentNumber") {
                                                  inputs.inputDocumentNumber = formData.controls[c].value;
                                                  // alert(formData.controls[c].name + " | " + formData.controls[c].value);
                                              }
                                  
                                              if (formData.controls[c].name === "inputDocumentRevision") {
                                                  inputs.inputDocumentRevision = formData.controls[c].value;
                                                  // alert(formData.controls[c].name + " | " + formData.controls[c].value);
                                              }
                                  
                                              if (formData.controls[c].name === "inputDocumentType") {
                                                  inputs.inputDocumentType = formData.controls[c].value;
                                                  // alert(formData.controls[c].name + " | " + formData.controls[c].value);
                                              }    
                                          }//End FOR
                                      doAction(theDocument, inputs, options);
                                      }
                                  
                                  
                                  function mainDialog(docRef, selectedItems, layers, inputs) {
                                  
                                  // Main Dialog
                                  // alert("Main Dialog: " + docRef.name);
                                  
                                  if ( docRef === undefined ) {
                                    alert("Cannot Execute, please select a document.");
                                  }
                                  
                                    var currentData = getMetaData();
                                  
                                    var dialogObj = {};
                                  
                                    dialogObj.groups = []; // An array of dialog groups
                                    dialogObj.title = "Update Meta Data";
                                  
                                    var groupLabelInfo = {};
                                    groupLabelInfo.title = "Edit: " + docRef.name;
                                    
                                    // Add Elements using JSON shorthand syntax
                                    groupLabelInfo.elements = [
                                      {
                                          "name":"labelECONumber",
                                          "type":"statictext",
                                          "value":"Engineering Change Order (ECO) Number",
                                          "visible":true
                                      },
                                      {
                                          "name":"inputECONumber",
                                          "type":"edittext",
                                          "value": currentData.inputECONumber,
                                          "visible":true
                                      },
                                  
                                      {
                                          "name":"documentName",
                                          "type":"statictext",
                                          "value":"Document Name",
                                          "visible":true
                                      },
                                      {
                                          "name":"inputDocumentName",
                                          "type":"edittext",
                                          "value": currentData.inputDocumentName,
                                          "visible":true
                                      },
                                  
                                      {
                                          "name":"documentNumber",
                                          "type":"statictext",
                                          "value":"Document Number",
                                          "visible":true
                                      },
                                      {
                                          "name":"inputDocumentNumber",
                                          "type":"edittext",
                                          "value": currentData.inputDocumentNumber,
                                          "visible":true
                                      },
                                  
                                  
                                      {
                                          "name":"documentRevision",
                                          "type":"statictext",
                                          "value":"Revision",
                                          "visible":true
                                      },
                                      {
                                          "name":"inputDocumentRevision",
                                          "type":"dropdownlist",
                                          "value": currentData.listRevisions,
                                          "visible":true,
                                          "selection":currentData.selectionRevision,
                                      },
                                  
                                      {
                                          "name":"documentType",
                                          "type":"statictext",
                                          "value":"Label Type",
                                          "visible":true
                                      },
                                      {
                                          "name":"inputDocumentType",
                                          "type":"dropdownlist",
                                          "value": currentData.listDocumentTypes,
                                          "visible":true,
                                          "selection":currentData.selectionDocumentType,
                                      },
                                  
                                    ];
                                  
                                  
                                    // Add to groups to list
                                    dialogObj.groups.push(groupLabelInfo);
                                    return dialogObj;
                                  }
                                  
                                  function doAction(docRef, inputs, options) {
                                  
                                  alert("doAction " + docRef.name + " \n INPUTS: \n" + inputs.reflect.properties + "\n\n OPTIONS: \n" + options.reflect.properties);
                                  
                                  
                                  // Get the current contents
                                  
                                  var fooContents = app.activeDocument.textVariables.item ('Foo').variableOptions.contents;
                                  var barContents = app.activeDocument.textVariables.item ('Bar').variableOptions.contents;
                                  
                                  
                                  alert("GET textVariable contents \n Foo: \n" + fooContents + "\n\n Bar: \n" + barContents);
                                  
                                  // Set/Update the contents
                                  // Why does this not seem to work?
                                  
                                  alert("SET textVariable contents \n Foo: \n" + inputs.inputDocumentName + "\n\n Bar: \n" + inputs.inputDocumentType);
                                  
                                  app.activeDocument.textVariables.item ('Foo').variableOptions.contents = inputs.inputDocumentName;
                                  app.activeDocument.textVariables.item ('Bar').variableOptions.contents = inputs.inputDocumentType;
                                  
                                  
                                  // Script does not seem to reach this point. Why?
                                  alert("END of doAction");
                                  }
                                  
                                  
                                  // A Factory function for creating dialog boxes
                                  
                                  function sfDialogFactory(dialog) {
                                    
                                      // A factory method for creating dialog screens
                                      
                                      // Dialog Window
                                      var d = new Window("dialog", dialog.title);
                                  
                                      // alert("Number of Inputs" + dialog.inputs.length);
                                      // alert("Number of Options" + dialog.options.length);
                                  
                                      var i; // counter
                                      var len; // length of array elements
                                  
                                      // Generate Groups
                                      if (dialog.groups.length > 0) {
                                             
                                          len = dialog.groups.length;
                                          for (i = 0; i < len; i++ )
                                          {
                                              var currentGroup = dialog.groups[i];
                                              inputGroup = d.add ("panel", undefined, currentGroup.title);
                                                  inputGroup.alignChildren = ["fill","fill"];
                                  
                                              if (currentGroup.elements.length > 0) {
                                                  // Add Elements
                                                  var ii;
                                                  var elemLen = currentGroup.elements.length;
                                                  for (ii = 0; ii < elemLen; ii++ )
                                                  {
                                                      var currentElement = currentGroup.elements[ii];
                                  
                                                      var el = inputGroup.add(currentElement.type, undefined, currentElement.value);
                                  
                                                      // Additional properties added for future reflection
                                                      el.elName = currentElement.name;
                                                      el.elIndex = ii;
                                  
                                                      switch(currentElement.type)
                                                      {
                                                          case "statictext":
                                                              el.visible = currentElement.visible;
                                                          break;
                                                          case "edittext":
                                                              el.visible = currentElement.visible;
                                                          break;
                                                          case "dropdownlist":
                                                              el.visible = currentElement.visible;
                                                              el.selection = currentElement.selection;
                                                              el.onChange = currentElement.onChange;
                                                          break;
                                                          case "checkbox":
                                                              el.visible = currentElement.visible;
                                                              el.value = currentElement.value;
                                                          break;
                                                          default:
                                                          throw new Error('Unknown Dialog Element Type [' + currentElement.type + ']');
                                                      }
                                  
                                                  }
                                              }
                                          }
                                      }
                                  
                                    // Buttons Group
                                    var buttonGroup = d.add("group");
                                    var bOK = buttonGroup.add("button", undefined, "Continue", {name: "ok"});
                                    var bCANCEL = buttonGroup.add("button", undefined, "Cancel", {name: "cancel"});
                                  
                                    return d;
                                  }
                                  function getControlValues(set) {
                                      elementsData = {};
                                      elementsData.controls = [];
                                      // TO DO Add more types
                                  
                                      var giLen = set.children.length;
                                      for (var gi = 0; gi < giLen; gi++ )
                                      {
                                          var child = set.children[gi];
                                          // alert(objReflection(child, "none", false));
                                          // alert(child.type);
                                          var control = {};
                                              control.name = child.elName;
                                              control.index = child.elIndex;
                                              control.type = child.type;
                                              control.visible = child.visible;
                                          switch(child.type)
                                          {
                                              case "statictext":
                                                  control.value = child.text;
                                              break;
                                              case "edittext":
                                                  control.value = child.text;
                                              break;
                                              case "dropdownlist":
                                                  control.value = child.selection.text;
                                              break;
                                              case "checkbox":
                                                  control.value = child.value;
                                              break;
                                              default:
                                              throw new Error('Unknown Dialog Element Type');
                                          }
                                          elementsData.controls.push(control);
                                          // alert(objReflection(control, "none", false));
                                      }
                                      return elementsData;
                                  }
                                  function getMetaData() {
                                  // Return a data structure that contains meta data from the document.
                                  
                                      var dataObject = {};
                                  
                                       // Default arrays
                                       dataObject.listRevisions = generateRangeOfNumbers ("r", 1, 100);
                                       dataObject.listDesignComps = generateRangeOfNumbers ("Comp_", 1, 100);
                                       dataObject.listDocumentTypes = [
                                                       "Datasheet",
                                                       "Manual",
                                                       "Tech Guide",
                                                       "Other"
                                                   ];
                                  
                                  
                                       // Set Sensible Default Values for the UI Form
                                       if (!dataObject.inputECONumber) {
                                           dataObject.inputECONumber = "###ECO###";
                                       }
                                  
                                       if (!dataObject.inputDocumentName) {
                                           dataObject.inputDocumentName = "Document Name";
                                       }
                                  
                                       if (!dataObject.inputDocumentNumber) {
                                           dataObject.inputDocumentNumber = "048-xxx-30";
                                       }
                                  
                                       if (!dataObject.inputDocumentRevision) {
                                           dataObject.inputDocumentRevision = "r01";
                                       }
                                  
                                       if (!dataObject.inputDocumentType) {
                                           dataObject.inputDocumentType = "Datasheet";
                                       }
                                  
                                  
                                       return dataObject;
                                  
                                  }
                                  
                                  
                                  function generateRangeOfNumbers (prefix, start, end) {
                                      // This function generates an array of sequential numbers within a range
                                      // prefix = string to append to beginning of each element
                                      // start = the beginning of the range
                                      // end = the end of the range
                                      // length = overall number of cycles to loop through, start and end must fall within this value
                                      
                                      var output = [];
                                      
                                      for ( var i = start; i <= end; i++ )
                                      {
                                          if (i < 10) {
                                              // Add a leading zero
                                              output.push(prefix + "0" + i);
                                          }
                                          else {
                                              output.push(prefix + i);
                                          }
                                      }
                                  
                                      return output;
                                  }
                                  
                                  
                                  //=================================================
                                  // END THE SCRIPT
                                  ///////////////////////////////////////////////////
                                  }
                                  
                                  theScript();
                                  

                                   

                                  I have modified your code little. It is working for me here. Check it...

                                   

                                  Thanks,

                                  Green4ever

                                  • 14. Re: How to change the "TextVariable" via javascript
                                    Gordon The Scripter Level 1

                                    Thank you very very much Green4ever.

                                     

                                    Just tried your code. It works for me and it makes sense now.

                                     

                                    Gordon