2

Long time user, first time asker; very new to regular expressions. I'm a designer trying to make my life in InDesign easier, so please be patient if this is an easy one :)

I'm working on a script that pulls pages out of a master file into a template file. Some of these master pages have layers that are to be used when the final file is exported to PDF for print; other layers are to be used when the final file is exported to e-mailing. So, if someone checks an option to save for e-mailing, I want the print layers to hide and the e-mail layers to show. Easy enough, but I wanted to streamline the code as a function so I could specify "print" or "email" as a variable, and then the script would match that to any variable that has "print" in it. Regex territory.

var openDocument = app.documents.item(0);
var LayerLength = openDocument.layers.length;

wordToMatch = "print";

for (i=0;i<LayerLength;i++)
{
    myRegEx = new RegExp(wordToMatch,"i");

    str = openDocument.layers.item(i).name;
    if (str.search(myRegEx) >= 0)
    {
        openDocument.layers.item(i).visible = true;
    }
}

So, this actually works. It does what I want it to do (Haven't put it in a function yet but I'll get there). It finds layers with "print" in them and then makes them visible.

This didn't seem ideal to me, though. I thought it would make more sense to define the regex once and then use it multiple times in the for loop, as follows:

wordToMatch = "print";
myRegEx = new RegExp(wordToMatch,"i");

for (i=0;i<LayerLength;i++)
{
    str = openDocument.layers.item(i).name;

    if (str.search(myRegEx) >= 0)
    {
        openDocument.layers.item(i).visible = true;
    }
}

But this only does what it's supposed to do on the first layer, then it's unable to match any subsequent layers.

Why is this? I feel like I'm misunderstanding something fundamental here, and I'd like to know what that is.

Thanks, Brendan

Brendan
  • 868
  • 1
  • 16
  • 38

1 Answers1

4

A regular expression has a lastIndex property- when a match is found, last index points at the next character after the match, resetting to 0 only after all the matches are found.

This is so you can find the next match in the same string- since you are only looking for the first match, reset the lastIndex yourself in the loop.

for(i= 0; i<LayerLength; i++){
    myRegEx.lastIndex= 0;
    str= openDocument.layers.item(i).name;
    if(str.search(myRegEx)>= 0){
        openDocument.layers.item(i).visible= true;
    }
}
kennebec
  • 102,654
  • 32
  • 106
  • 127
  • This worked. So thank you very much :) But I still don't quite understand the principle here, so if you have time for a followup I'd appreciate it! I took out the line you added and put an alert in to show myRegEx.lastIndex just before the closing brace of the for loop. After the first iteration it was 9 (Layer named "For Print Only" so that makes sense), but after every other one it was -1. If I'm understanding what you said correctly, wouldn't it be at 9 every time? – Brendan Mar 16 '12 at 19:53
  • How is this relevant when `/g` is not used? Quote from MDN `This property is set only if the regular expression used the "g" flag to indicate a global search`. Thus it should have no effect at all. – Qtax Mar 16 '12 at 20:48
  • I don't know, but it worked. Could this just be a difference between how InDesign handles JS compared to the Web? I don't know enough to know the full extent of the differences between the two. – Brendan Mar 16 '12 at 21:06