4 Replies Latest reply on Aug 29, 2011 2:55 AM by Nye Hughes

    [JS CS5] Find widest number in a numbered list

    Nye Hughes

      I am trying to automate as far as possible the process to set up a decimal align numbered list as detailed in this Indesign Secrets post. The first part of this requires recording the width of the widest number in the current numbered list.

       

      My approach so far is to try to use FindText() to make an array of all the paras with a particular list style. I was then planning on processing them to find the widest number. However, straight away I am running into difficulties. The first problem is I am unable to set the findTextPrefences to search only for the the [Default] list style. If you set this via the UX the object browers, shows the AppliedNumberingList as [Object Color] which I am presuming is a bug? So my questions:

       

      – Can anyone provide a workaround that allows a FindText() for Para with List Name [default]?

       

      – Thinking about the next stage, if I get that far, can anyone think of simple way to find the widest number from the search results?

       

      – or am I going about this completely the wrong way?

       

      Any help or thoughts would be appreciated.

       

      Thanks, Nye

        • 1. Re: [JS CS5] Find widest number in a numbered list
          Roy Marshall Level 1

          Hi Nye.

           

          I am not 100% certain of what you are asking, but let me explain what I have done with something myself, I think it is similar to what your question is.

           

          Look at this link

          http://youtu.be/Bj59LVcaYZE

          What this script does (and crudely I must add) is look at the different column width requirements for the tabs, and sets up the tab stops to allow for the widest column.

           

          As a very quick overview, this is done by getting the horizontal offset of a the first character (x) getting the offset of the tab character (y) and extracting x from y (z).  Repeat this for each line, overidding z if the new z is greater.

           

          You will then have the maximum tab stop value to use that will cater for all instances.

           

          If this makes any sense to you, and reading it back myself will not be suprised if it doesn't, I can let you have the script to pull apart if you want to.

           

          Anyway, it would be interesting to hear if I am even on the right lines here!

           

          Cheers

           

          Roy

          1 person found this helpful
          • 2. Re: [JS CS5] Find widest number in a numbered list
            Nye Hughes Level 1

            Roy

             

            Thanks for your input, and yes, the script you demo on Youtube looks like it would have solve similar problems to mine. I would be interested to see your script.

             

            In the end I soldiered on and ended up with this, which seems to work ok:

             

            /*  A script to set up decimal-aligned numbered list as described 
                in http://indesignsecrets.com/built-to-list.php, by Nye Hughes 2011
            
                To use (at own risk!): set up a numbered list (e.g. by parastyle), 
                place the cursor in any paragraph within this list, then run the script. 
                The script calculates the width of the widest list-number, then uses this to set up 
                the Bullet or Number Position settings for the selected para to give perfect 
                right-aligned numbered List. For further info see http://indesignsecrets.com/built-to-list.php
            
            */
            
            // get active doc
            var myDoc = app.activeDocument;
            
            // get current para
            var myPara = app.selection[0].paragraphs[0];
            
            // is the Para a numbered list? If not exit with an alert
            if (myPara.bulletsAndNumberingListType == ListType.numberedList) {
            
                //best to stick to using points just now, so store old units
                var myOldXUnits = app.activeDocument.viewPreferences.horizontalMeasurementUnits;
                 var myOldYUnits = app.activeDocument.viewPreferences.verticalMeasurementUnits;
                var myOldRulerOrigin = app.activeDocument.viewPreferences.rulerOrigin;
            
                // and set doc up as points for measurements
                 app.activeDocument.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.points;
                 app.activeDocument.viewPreferences.verticalMeasurementUnits = MeasurementUnits.points;
                app.activeDocument.viewPreferences.rulerOrigin = RulerOrigin.spreadOrigin;    
            
            
                // check what list this para is a member of?
                var myNumberingListName = myPara.appliedNumberingList.name;
            
              // use findText to get a list of all other members of this list 
                app.findTextPreferences = null;
                app.findTextPreferences.bulletsAndNumberingListType = ListType.numberedList;
                app.findTextPreferences.appliedNumberingList = myNumberingListName; // you have to pass this by name, because you get an error message if you actualy pass a numberingList object!
            
                     app.changeTextPreferences = null;
                     myFinds = myDoc.findText();
                     myCounter = myFinds.length-1;
                     var widest = 0;
                     do {  // process backwards 
                           var currentWidth = getWidthOfNumber(myFinds[myCounter]) ;
                           widest = Math.max (widest, currentWidth);
                       myCounter --; 
                     }  while (myCounter > -1);
            
            
                     // Prompt for the gap between the list-number and the entry. Default to a em space
            
                     var gapWidth = myPara.insertionPoints[0].pointSize;
            
                     // Make the dialog box 
                        var the_dialog = app.dialogs.add({name:"Enter the required gap width:"});
                        with(the_dialog.dialogColumns.add()){
                            with(dialogRows.add()){
                                with(dialogColumns.add()){
                                    staticTexts.add({staticLabel:"Gap width:"});
                                }
                                with(dialogColumns.add()){
                                     var GapWidthField = measurementEditboxes.add({editValue:gapWidth, editUnits: MeasurementUnits.POINTS});
                                }
                            }
                        }
            
                        // show the dialog
                        var myReturn = the_dialog.show();
                            if (myReturn == true){
                                //Get the values from the dialog box.
                                gapWidth = GapWidthField.editValue;
                                the_dialog.destroy();
            
                            }
                            else{
                                the_dialog.destroy();
                                exit();
                            }
            
                          $.writeln ( widest);        
                         // finally, plug the measurements for the selected paragraph
                         // myPara.numberingExpression = "^#^t";
                         myPara.numberingAlignment = ListAlignment.rightAlign;
                         myPara.leftIndent = (gapWidth + widest);
                         myPara.firstLineIndent = -gapWidth;
            
            
            
            // restore measurements
                 app.activeDocument.viewPreferences.horizontalMeasurementUnits = myOldXUnits;
                 app.activeDocument.viewPreferences.verticalMeasurementUnits = myOldYUnits;
                app.activeDocument.viewPreferences.rulerOrigin = myOldRulerOrigin;
            }
            else {
                alert ("Paragraph needs to part of a numbered list");
                }
            
            // FUNCTIONS
            
            function getWidthOfNumber(myFoundPara) {
            
                    // get the formating from the found para
                   var thisNumber = myFoundPara.numberingResultNumber;
                   var thisNumberingCharacterStyle = myFoundPara.numberingCharacterStyle;
                   var theSize = myFoundPara.characters[0].pointSize;
                   var theFont = myFoundPara.characters[0].appliedFont;
                   var theTracking = myFoundPara.characters[0].tracking;
            
                   // make a temp text frame with the List number as contents
                   var tf = app.activeDocument.textFrames.add (
                  {
                  geometricBounds: [0,0,40,40],
                  contents: thisNumber + ""}
                  );
                  var myTempListNumber = tf.parentStory.words[0]; 
            
            
                  // Format the list number to match the orginal Para
                  myTempListNumber.pointSize = theSize;
                  myTempListNumber.appliedFont = theFont;
                  myTempListNumber.tracking = theTracking;
                  myTempListNumber.appliedCharacterStyle = thisNumberingCharacterStyle;
            
                   // calcuate the list from the offset
                   var numWidth = myTempListNumber.endHorizontalOffset - myTempListNumber.horizontalOffset;
            
                  // ditch the temp frame 
                   tf.remove();
            
                   return numWidth
            
                }
            

             

            If anyone finds the process of setting up these lists manually as tiresome as me, I hope this is of some help.

             

            Nye

            • 3. Re: [JS CS5] Find widest number in a numbered list
              John Hawkinson Level 5

              I'm afraid this is too complicated for me to go through right now. Could you break it down into a much smaller test case? Or maybe someone else has time...

              • 4. Re: [JS CS5] Find widest number in a numbered list
                Nye Hughes Level 1

                @John

                 

                No need for help anymore, the script I posted is the working version, in case of any interest or use to anyone. I should probably spell out the 2 bits of weirdness I had to work around though for anyone else who is attempting to work with numbered lists via scripting:

                 

                1. Most likely you'll be using FindText or FindGrep to gather up the paras within a particular list and so need to set the findTextPreferences.AppliedNumberingList to the list you are interested in. However, if you try and set this to a [NumberingList object] you get an error "Expected a NumberingList got a NumberingList"! Using the name of the numbering list as a string does work.
                2. If you use the UX to set the Find What Preferences to numbering List [Default], then examine the value for findTextPreferences.AppliedNumberingList via scripting, it is set as [Object Color]. It should be [Object NumberingList]. Therefore, you can't safely work with this value via scripting.

                 

                I have commented the script fairly comprehensively so it should be clear how I worked round these problems, and how the script works in general.

                 

                Nye