6 Replies Latest reply on Sep 6, 2011 8:12 AM by MatthewMariani

    [JS][CS5.5][ScriptUI] ScriptUI event handler issue

    MatthewMariani Level 1

      I built a pie graph script starting with  Mariusz Sobolewski's 2005 Pie Graph script available in the Exchange, and I am trying

      to implement a basic graph style functionality in InDesign and a ScriptUI user inferface to enable its use.

       

      I define global variables to keep track of  parameters that the user will choose in a ScriptUI dialog.

      The problem is that I can't get event handlers to update values of 8 dropdownlist controls to the globally defined JavaScript object which is ultimately to be used by a Pie Graph constructor .

       

      I can  update the values of several checkbox controls to a globally defined array, but can't figure out how to make it work for the dropdownlist controls which indicate the object style to be applied to each slice of the pie.

       

      Can anyone help? See code below:

       

      #target "InDesign-7.5"
      var graphStyleFiles = getStyleFiles();
      var graphStyleNames = new Array(), pStyNames = new Array(), oStyNames = new Array(), oStyGroupNames = new Array(), pStyGroupNames = new Array();
      var graphStyle = readGraphStyle(graphStyleFiles[0]);
      /*
      resulting default graph style is JavaScript object:
      graphStyle = {
          objectStyleGroup: "graph",
          paraStyleGroup: "graph-styles",
          legendTextParaStyle: "legend_1",
          labelTextParaStyle: "label_1",
          sliceObjectStyles: [ "osty_1", "osty_2", "osty_4", "osty_3", "osty_7", "osty_5", "osty_0", "osty_6" ]
      }
      */
      
      //Global to track which slices should "explode" based on user selections
      var explosionIndices = [];
      ...
      rslt = showOptionsDialog( zValues, zLegendTexts);
      ...
      var aPieGraph = new Pie( circle, dataValues );
      aPieGraph.explodeSlices( explosionIndices );
      ...
      function Pie( zCircle, zValues ) { 
      ...
      }
      //show options for pie graph with ScriptUI dialog
      function showOptionsDialog( vals, texts ){
          ...
          //onClick handler to update indices of selected checkboxes (all contained in a parent panel) that indicate whether a given slice of pie is to be exploded
          //THIS WORKS: IT UPDATES the GLOBAL VARIABLE "explosionIndices"
          function updateExplosionIndices() {
              explosionIndices.length = 0;
              for ( var i = 0; i < this.parent.children.length; i++ ) {
                  if ( this.parent.children[i].value ) explosionIndices.push( i );
              }
          }
          //onChange handler for dropdownlist controls (all contained in a parent panel) that map each pie slice to an object style
          //THIS DOES **NOT** WORK. IT DOES NOT UPDATE THE GLOBAL OBJECT "graphStyle"
          function objectStyleItemPickerReact() {
              graphStyle.sliceObjectStyles.length = 0;
              for ( var i = 0; i < this.parent.children.length; i++ ) {
                 graphStyle.sliceObjectStyles[this.parent.children[i].selection.index] = this.parent.children[i].selection.text;
               }
          }
          ...
      }
      
        • 1. Re: [JS][CS5.5][ScriptUI] ScriptUI event handler issue
          John Hawkinson Level 5

          Is the problem that your event handler seems to have trouble updating global state, or that it is not called at all?

          What happens when you $.writeln() the relevant values from within your event handler?

          Perhaps you should be using a persistent engine, i.e. #targetengine session.

           

          My off-the-cuff guess is that your problem stems from the use of this, and you are better off avoiding new/this and sticking with prototypical (prototypal?) inheritance, or even no inheritance...

          1 person found this helpful
          • 2. Re: [JS][CS5.5][ScriptUI] ScriptUI event handler issue
            MatthewMariani Level 1

            Thanks for your insights! Will keep these in mind in future. I tried using a session engine but that did not help. Sometimes it seemed the handler was not called at all and sometimes it updated only some of the values that needed updating. I ended up making it work by adding a listener to each of the 8 dropdowns as shown below...

             

            ...
            dd.addEventListener( "change", ddOstyPickerHandle );
            ...
                function ddOstyPickerHandle(evt) {
                   for (var i = 0; i < evt.target.parent.children.length; i++ ) {
                        graphStyle.sliceObjectStyles[i] = evt.target.parent.children[i].selection.text;
                   }
                    evt.stopPropagation();
                 }
            

            • 3. Re: [JS][CS5.5][ScriptUI] ScriptUI event handler issue
              Marc Autret Level 4

              Hi Matthew,

               

              Your original code contains a very strange line:

               

              graphStyle.sliceObjectStyles[this.parent.children[i].selection.index] = this.parent.children[i].selection.text;

               

              Given a dropdownlist this.parent.children[i], you are using the index of its selected item as a new index of the array graphStyle.sliceObjectStyles, which you are reassigning from scratch. So your algorithm looks like:

               

              // myArray is an empty array (myArray.length = 0)

              for each( widget ) { myArray[widget.selection.index] = something; }

               

              Are you sure you want to remap the array this way? Suppose that A.selection.index == 2 and B.selection.index == 2 (i.e. the third item is selected in two different drop down lists). Then your loop will assign myArray[2] twice! In addition, nothing prevents the resulting array from having 'holes' (=undefined indices).

               

              Maybe this explains your bug.

               

              Beyond that, I find it odd to traverse this.parent.children from an event handler. Of course I can't assume anything about the hidden part of your snippet, but what is confusing here is the way you connect objectStyleItemPickerReact to the corresponding widget(s). You don't seem to attach this event handler to the parent panel. Why? Provided that the 'change' event bubbles, you just could use sth like:

               

                 parentPanel.addEventListener('change', objectStyleItemPickerReact)

               

              and then work from the evt.target widget in your change event handler.

               

              Usually when we have a set of similar widgets that need to share a same behavior, it is possible to use a single listener (attached to the parent object). Here is a simple example with dropdown lists:

               

              var NB_OF_WIDGETS = 5;
              
              var  u, // undefined shortcut
                   dlg = new Window('dialog'),
                   pn = dlg.add('panel'),
                   i;
              
              // Add some dropdownlists in the panel
              for( i=0 ; i < NB_OF_WIDGETS ; ++i )
                   pn.add('dropdownlist',u,["aaa","bbb","ccc"],{idx:i}).selection = i%3;
              
              function myChangeHandler(ev)
                   {
                   // NB: <this> is the parent container (==pn)
                   var wg = ev.target,
                        sel = (wg instanceof DropDownList)&&wg.selection;
                   
                   if( false !== sel )
                        alert(['DropDownList: ' + wg.properties.idx,'Selection: ' + sel.text].join('\r'));
              
                   wg = sel = null;
                   }
              
              pn.addEventListener('change', myChangeHandler);
              dlg.show();
              

               

              Hope that helps.

               

              @+

              Marc

              • 4. Re: [JS][CS5.5][ScriptUI] ScriptUI event handler issue
                MatthewMariani Level 1

                Thank you Marc! Very instructive and helpful. My first inclination was to add the listener to the parent panel containing the dropdownlists, but it wasn't clear to me how the handler would be able to determine which of the dropdowns was firing off the change event. Your example has the line:

                 

                pn.add('dropdownlist',u,["aaa","bbb","ccc"],{idx:i}).selection = i%3;

                 

                I was not aware of a creation property, idx. I can't find any documentation of this. Is it possible to add any arbitrarily named creation property and then access it later via the properties object? I read in the Object Model Viewer that creation properties are only used when an object is created, but this line of code of yours makes it seem like this is not the case:

                 

                alert(['DropDownList: ' + wg.properties.idx,'Selection: ' + sel.text].join('\r'));

                 

                Thanks again!

                • 5. Re: [JS][CS5.5][ScriptUI] ScriptUI event handler issue
                  Marc Autret Level 4

                  MatthewMariani wrote:

                   

                  (...) Your example has the line:

                   

                  pn.add('dropdownlist',u,["aaa","bbb","ccc"],{idx:i}).selection = i%3;

                   

                  I was not aware of a creation property, idx. I can't find any documentation of this. Is it possible to add any arbitrarily named creation property and then access it later via the properties object? I read in the Object Model Viewer that creation properties are only used when an object is created, but this line of code of yours makes it seem like this is not the case:

                   

                  alert(['DropDownList: ' + wg.properties.idx,'Selection: ' + sel.text].join('\r'));

                   

                   

                  Yep! This is one of many underdocumented ScriptUI features. I don't remember whether Peter Kahrel mentions it in its "ScriptUI for Dummies" guide. Indeed, you can add any arbitrarily property in the 'creation properties' object (= the last argument of the add method). Such extra properties are then available in myWidget.properties. This technique has two benefits: 1) it allows to declare the extra properties during the creation of the widget, 2) it avoids any collision with the regular (documented) properties. Of course the only limitation is that you cannot use the name of an existing creation property ;-)

                   

                  @+

                  Marc

                  1 person found this helpful
                  • 6. Re: [JS][CS5.5][ScriptUI] ScriptUI event handler issue
                    MatthewMariani Level 1

                    Thanks for the confirmation, Marc. I would not have attempted my current

                    project without reading Peter Kahrel's excellent Script UI guide. It was

                    very helpful. He does talk about creation properties versus normal

                    properties, but I may have just missed the point about being able to define

                    your own creation properties. Very good to know. Thanks for filling in that

                    gap in the official documentation!