InDesign JavaScript: Copying GREP Styles

Recently one of our clients asked us to bring some InDesign templates up to their corporate specs. Part of this was inserting a set of GREP styles into the styles already contained in the documents. GREP styles are great ways to automatically apply formatting to particular text whenever it is entered, removing the obligation from the user to remember what phrases are non-breaking or italicized. Unfortunately, if you have to add GREPs to many existing style, the process is repetitive, slow and error-prone. The solution is InDesign JavaScript.


InDesign JavaScript to the Rescue!

The solution is a script. InDesign has good support for JavaScript, which works for both Windows and OSX versions of InDesign. The down-side to InDesign scripting is that there is not as much knowledge out there on the web, at least when you compare it to JavaScript for HTML. So, in the spirit of increasing human-kind's knowledge base, here is a script for copying GREP styles. The original code came from a script found on the Adobe Community forums. Then we added the ability to work with styles that are in style groups, up to 2 levels deep. Enjoy!

//This utility will copy GREP styles into styles that are nested in up to two levels of groups i.e. Main Style Group>Headings Group>Heading 1
//Copy the text below to a text editor like NotePad or TextEdit, then save as a file with a “.js” ending.
//Copy it into the Scripts Panel folder inside the Scripts folder inside the InDesign application folder. 
//Create a style at the lowest level of the Paragraph Styles i.e. NOT in a style group.
//Put all the GREP styles you wich to copy into this style.
//Type the style name between quotes in the line below. Then run the script and select the styles to which you want to copy the GREP styles.
var source = 'GREPSourceStyle';
var theDoc = app.activeDocument;  
var pStyles = theDoc.allParagraphStyles;
var pStyleStringList = []; 
fillpStyleStringList();  
var getpStyleIndexinpStyles = selectpStyle(pStyleStringList);
var selectedpStylesByName = getSelectedpStyleNames(getpStyleIndexinpStyles);
l = selectedpStylesByName.length;

while(l--){setGrepStyle([selectedpStylesByName[l][0]],[selectedpStylesByName[l][1]],[selectedpStylesByName[l][2]])}
 
function fillpStyleStringList(){  
  for(i = 0 ; i < pStyles.length; i++){  
    if(pStyles[i].parent.parent.toString() === '[object ParagraphStyleGroup]'){
      pStyleStringList.push('Group: ' + pStyles[i].parent.parent.name + ', Subgroup: ' + pStyles[i].parent.name + ', Name: ' + pStyles[i].name);
    }else if(pStyles[i].parent.toString() === '[object ParagraphStyleGroup]'){
      pStyleStringList.push('Subgroup: ' + pStyles[i].parent.name + ', Name: ' + pStyles[i].name);
    }else{
      pStyleStringList.push('Name: ' + pStyles[i].name);
    }
  }
}

function selectpStyle (array){
  var myWindow = new Window ("dialog", "Please select your target paragraph styles.");
  var myInputGroup = myWindow.add ("group");
  var select = myInputGroup.add ("listbox", [0, 0, 300, 300], array, {scrolling: true, multiselect: true});
  var myButtonGroup = myWindow.add ("group");
  myButtonGroup.add ("button", undefined, "OK");
  myButtonGroup.add ("button", undefined, "Cancel");
  if (myWindow.show() == 1){
    var mySelection = select.selection;
    var tmpList = [];
    for(g = 0; g < mySelection.length; g++){
      tmpList.push(mySelection[g].index);
    }
    return tmpList;
    myWindow.close();
  }else{
    exit();
  }
}

function getSelectedpStyleNames(getpStylesIndexinpStyles){
  var currentTargetpStyleName;
  var SelectedNameArray = new Array();
  for(j = 0; j < getpStylesIndexinpStyles.length; j++){
    var tempArray = new Array(2);
    currentTargetpStyleName = pStyles[getpStyleIndexinpStyles[j]].name;
    currentTargetpStyleSubgroup = pStyles[getpStyleIndexinpStyles[j]].parent.name;
    currentTargetpStyleGroup = pStyles[getpStyleIndexinpStyles[j]].parent.parent.name;
    tempArray[0] = currentTargetpStyleGroup;
    tempArray[1] = currentTargetpStyleSubgroup;
    tempArray[2] = currentTargetpStyleName;
    SelectedNameArray[j] = tempArray;
  }
  return SelectedNameArray;
}

function setGrepStyle(targetGroup, targetSubgroup, targetName){
  var target
  error = "";
  basepStyle = theDoc.paragraphStyles.item(source);
  if (!basepStyle.isValid) error = 'Source style does not exist';
  if(targetGroup != "" && targetGroup != theDoc.name && targetGroup != app.name){
    var temptarget = theDoc.paragraphStyleGroups.itemByName(targetGroup.toString());
    target = temptarget.paragraphStyleGroups.itemByName(targetSubgroup.toString()).paragraphStyles.itemByName(targetName.toString());
  }else if(targetSubgroup != "" && targetSubgroup != theDoc.name && targetSubgroup != app.name){
    target = theDoc.paragraphStyleGroups.itemByName(targetSubgroup.toString()).paragraphStyles.itemByName(targetName.toString());
  }else{
    target = theDoc.paragraphStyles.itemByName(targetName.toString());
  }
  if (!target.isValid) error += 'rTarget style does not exist';
  if (error != ""){alert (error); exit()}
    gs = basepStyle.nestedGrepStyles;
  for (i = 0; i < gs.length; i++){
    target.nestedGrepStyles.add (gs[i].properties);
  }
}