Help adjusting a script I found to change text frame object style based on paragraph style

Participant ,
Apr 25, 2022 Apr 25, 2022

Copy link to clipboard

Copied

I found this great script where you pick an assigned 'object style' and it will move all items of that style to the layer you pick. I'm trying to tweak it so it will instead change any text frames with a specified paragraph style and assign it with an object style.

 

I got the first part changed, but I need help with:

  • first part: language to include all items that are in folders within both paragraph and objects styles. right now it just pulls items that are not in folders
  • The second part: code originally moved item in first selection to layer in the second selection ... instead I want it to find all frames containing paragraph style from first selection and assign object style from second selection.

 

Any help would be great! Thank you!

 

//This script moves paragraphs with selected paragraph style to selected layer
var myDoc = app.activeDocument;

var w = new Window ("dialog", "Choose paragraph Style and Layer", undefined, {closeButton: true});
w.orientation = "row";
w.alignChildren = ["right", "center"];

w.add("statictext", undefined, "Assign all frames with");
var paragraphStyle = w.add("dropdownlist", undefined, myDoc.paragraphStyles.everyItem().name); // paragraph style list -- what do i adjust to include items within folders too?
paragraphStyle.selection = 0;

w.add("statictext", undefined, "style as");
var applyObjStyle = w.add("dropdownlist", undefined, myDoc.objectStyles.everyItem().name); // objectStyles list -- what do i adjust to include items within folders too?
applyObjStyle.selection = 0;

var button = w.add ("button", [0,0,96,20], "OK", {name: "Ok"});

var paraStyleName, objStyleName;

button.onClick = function(){
    paraStyleName = paragraphStyle.selection.text;
    objStyleName = applyObjStyle.selection.text;    
    w.close();
}
w.show();
//NEED HELP WITH CODE BELOW TO assign paraStyleName with objStyle Name
var pageItems = myDoc.pageItems;

if (parseFloat(app.version) < 6) // "app.version < 6" if it's running under an earlier version than CS4, as earlier versions don't support "Undo" in scripts
    doUndoWrapper();
else
    app.doScript(doUndoWrapper, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Move to layer");
//< END OF doUndoWraper

function doUndoWrapper(){
    // unlock locked objectStyles
    var lockedobjectStyles = {};
    for(var layer = 0; layer < myDoc.objectStyles.length; layer++){
        lockedobjectStyles[myDoc.objectStyles[layer].name] = myDoc.objectStyles[layer].locked;
        myDoc.objectStyles[layer].locked = false;
    }    
    
    if(paraStyleName && objStyleName){
        //for(var i = 0; i < pageItems.length; i++){
        for(var i = --pageItems.length; i >= 0; i--){
            if(pageItems[i].appliedparagraphStyle.name === paraStyleName && pageItems[i].itemLayer.name != objStyleName){
                try{
                    // unlock locked paragraphs
                    var paragraphWasLocked = false;                
                    if(pageItems[i].locked){
                        paragraphWasLocked = true;
                        pageItems[i].locked = false;
                    }               
                
                    // move paragraphs to layer
                    pageItems[i].itemLayer = myDoc.objectStyles.item(objStyleName);
                    
                    // proceed until you bleed, lol!
                    var iterator = 0;
                    while(iterator < 1000 && pageItems[i].itemLayer.name != objStyleName){
                        pageItems[i].itemLayer = myDoc.objectStyles.item(objStyleName);
                        iterator++;
                    }                    
                    
                    // locking back locked paragraphs
                    if(paragraphWasLocked){
                        pageItems[i].locked = true;
                    }
                }catch(e){
                    alert(e, "Script Error", true);
                }
            }
        }
    }    
}

 

TOPICS
Scripting

Views

243

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 25, 2022 Apr 25, 2022

Copy link to clipboard

Copied

Hi @LynxKx,

I've written a bare bones script to do what (I think) you want. I haven't modified your existing script though, so you might need to meld them together. For example my script uses a hard-coded lookup array of paragraph style to object style pairs, so you may want to incorporate your existing UI for that part. See how you go with that—it will be a great exercise I hope, but let me know if you get stuck. I have written the getByName function to handle object styles in folders.

- Mark

 

 

/*

    Set Object Style by Paragraph Style
    for Indesign 2022

    by m1b
    here: https://community.adobe.com/t5/indesign-discussions/help-adjusting-a-script-i-found-to-change-text-frame-object-style-based-on-paragraph-style/m-p/12903549
*/


// array of paragraph-style-to-object-style lookups
// note: if two lookups match the same text frame
// only the first will be applied
var lookups = [
    { paragraphStyleName: 'Green', objectStyleName: 'Blue' },
    { paragraphStyleName: 'Blue', objectStyleName: 'Green' }
]


function main() {

    var doc = app.activeDocument,
        textFrames = doc.textFrames;

    // resolve the objectStyle for each lookup
    for (var i = 0; i < lookups.length; i++) {
        var objectStyle = getByName(doc.allObjectStyles, lookups[i].objectStyleName);
        if (objectStyle != undefined && objectStyle.isValid) {
            lookups[i].objectStyle = objectStyle;
        }
        else {
            alert('Could not find object style "' + lookups[i].objectStyleName + '" in document.');
            return;
        }
    }

    // look through each text frame for paragraphs with style
    var counter = 0;
    textFrameLoop:
    for (var i = 0; i < textFrames.length; i++) {
        for (var j = 0; j < lookups.length; j++) {
            var lookup = lookups[j];
            if (hasAppliedParagraphStyle(textFrames[i], lookup.paragraphStyleName)) {
                // found a match, so apply the object style
                textFrames[i].appliedObjectStyle = lookup.objectStyle;
                counter++;
                continue textFrameLoop;
            }
        }
    }

    // finished
    alert("Changed " + counter + " text frame's object styles.");

    function hasAppliedParagraphStyle(textFrame, paragraphStyleName) {
        // returns true if any paragraph of textFrame
        // has paragraphStyle paragraphStyleName applied
        var paras = textFrame.paragraphs;
        for (var i = 0; i < paras.length; i++) {
            if (paragraphStyleName == paras[i].appliedParagraphStyle.name)
                return true;
        }
        return false;
    }

    function getByName(styles, name) {
        for (var i = 0; i < styles.length; i++)
            if (styles[i].name == name)
                return styles[i];
    }

} // end main

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Set Object Style by Paragraph Style');

 

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Apr 26, 2022 Apr 26, 2022

Copy link to clipboard

Copied

maybe if i break it down a little further, i could probably figure it out if someone can help with the dropdown list. I need to have all my ObjectStyles pulled into a dropdownlist where it also references the folder name they live in.

 

var applyObjStyle = w.add("dropdownlist", undefined, myDoc.objectStyles.everyItem().name); // how do I adjust this language to include all styles in folder and preferrably show the folder name with the style as well
applyObjStyle.selection = 0;

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Apr 26, 2022 Apr 26, 2022

Copy link to clipboard

Copied

this code does work great to get the what I need done for right now, I just dont want to have to make a new script for every occurance that comes up. Thank you! I'm going to try and take pieces and see if I can get my original concept to work with how you set this up!

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Apr 26, 2022 Apr 26, 2022

Copy link to clipboard

Copied

in case anyone wants it ... i jsut figured out the object list part 

 

myObjStyles = myDoc.allObjectStyles;
var myObjStylesList = [];
for (i = 0; i < myObjStyles.length; i ++){
myObjStylesList[i] = myObjStyles[i].name;
if (myObjStyles[i].parent.constructor.name == "ObjectStyleGroup") myObjStylesList[i]+=" ["+myObjStyles[i].parent.name+"]";
}

w.add("statictext", undefined, "Move all objects with");
var list1 = w.add("dropdownlist", undefined, myObjStylesList); // Object style list
list1.selection = 0;

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Apr 27, 2022 Apr 27, 2022

Copy link to clipboard

Copied

REALLY WISH I could edit my posts! ... my code is pulling in the styles now but the action in the code isnt working when I select one thats in a folder.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 27, 2022 Apr 27, 2022

Copy link to clipboard

Copied

Hi @LynxKx, you are making progress! By the way, you should be able to edit your posts here. Click on the "More" button under your post and "Edit Reply".

If you want to show the style folders, perhaps you could make an array myStylesArray of objects that are something like this:

{
    styleName: "myObjectStyle", // just the style name
    folderName: "myStyleFolder" // this could be left undefined
    style: myObjectStyle  // the actual style
}

Then make the drop down menu by iterating over this array and adding either just the styleName property, or prefixing with the folderName, eg.

myStylesArray[i].folderName == undefined ? '' : myStylesArray[i].folderName + '/' + myStylesArray[i].styleName;

 - Mark

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Apr 28, 2022 Apr 28, 2022

Copy link to clipboard

Copied

I'm not sure if its because I'm just a 'participant' ... but I dont have those edit options for my posts 😕

 

I'd like to be able to use the script for mutliple things, and some files may or may not have the same folders and styles, so listing out any specific ones wont work ... i've got the code to pull in all the styles ... but the final script doesnt work if I select a style that is in a folder.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 29, 2022 Apr 29, 2022

Copy link to clipboard

Copied


@LynxKx wrote:

I'm not sure if its because I'm just a 'participant' ... but I dont have those edit options for my posts 😕

That's weird. I've always been able to edit my posts. Have you tried a different browser? See my screenshot.

 


@LynxKx wrote:

... but the final script doesnt work if I select a style that is in a folder.


That's why you need something like my getByName function. It works even if the style is in a folder.

- Mark

 

Screen Shot 2022-04-30 at 3.26.07 pm.png

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 27, 2022 Apr 27, 2022

Copy link to clipboard

Copied

Hi @LynxKx , here’s a version that uses the InDesign dialog class to return the selected styles—osSel & psSel return the dialog’s selected Object and Paragraph styles

 

 

 

makeDialog();
var osSel, psSel;
function makeDialog(){

    var theDialog = app.dialogs.add({name:"Dialog Components", canCancel:true});
    with(theDialog){
        with(dialogColumns.add()){
                with(dialogColumns.add()){
                    staticTexts.add({staticLabel:"Object Styles:"});
                    staticTexts.add({staticLabel:"Paragraph Styles:"});
                }
                with(dialogColumns.add()){
                    osSel = dropdowns.add({stringList:getStyles(app.activeDocument.allObjectStyles), selectedIndex:0, minWidth:80});
                    psSel = dropdowns.add({stringList:getStyles(app.activeDocument.allParagraphStyles), selectedIndex:0, minWidth:80});
                } 
        }
        if(theDialog.show() == true){
            osSel = app.activeDocument.allObjectStyles[osSel.selectedIndex];
            psSel = app.activeDocument.allParagraphStyles[psSel.selectedIndex];
            main();
            theDialog.destroy();
        }
    }
}


function main(){
    alert("\rChosen Object Style: " + osSel.name + "\rChosen Paragraph Style: " + psSel.name);
    return 
}



/**
* Returns a list of style names from the provided array of styles
* @ param the object array 
* @ return array of names 
*/
function getStyles(p){
    var a = new Array;
    for(var i = 0; i < p.length; i++){
        a.push(p[i].name);
    }
    return a
}

 

 

 

Screen Shot 35.pngScreen Shot 36.png

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
May 10, 2022 May 10, 2022

Copy link to clipboard

Copied

I won't tackle the entire script, but I will offer my functions for gathering styles, which might help that part anyway. Or help anyone else who happens upon this discussion looking for a solution to gathering styles. Character, Object, and Paragraph styles all have the same problem that "sub-styles" (items inside subfolders in the list) are not included in the top level style array. Here are my three functions that each get the root sytles plus all in style groups too. The functions return an array of the style objects. To use, call any of them and pass the active document.

 

// To use call and pass active document.
// For example...
var characterStyles = getCharacterStyles(app.activeDocument);
// etc.

function getCharacterStyles(o) {
    var a = [];
    var i;
    // Root styles.
    for (i = 0; i < o.characterStyles.length; i++) {
        a.push(o.characterStyles[i]);
    }
    // Style groups.
    for (i = 0; i < o.characterStyleGroups.length; i++) {
        // Recursive; calls itself.
        a = a.concat(getCharacterStyles(o.characterStyleGroups[i]));
    }
    return a;
}

function getObjectStyles(o) {
    var a = [];
    var i;
    // Root styles.
    for (i = 0; i < o.objectStyles.length; i++) {
        a.push(o.objectStyles[i]);
    }
    // Style groups.
    for (i = 0; i < o.objectStyleGroups.length; i++) {
        // Recursive; calls itself.
        a = a.concat(getObjectStyles(o.objectStyleGroups[i]));
    }
    return a;
}

function getParagraphStyles(o) {
    var a = [];
    var i;
    // Root styles.
    for (i = 0; i < o.paragraphStyles.length; i++) {
        a.push(o.paragraphStyles[i]);
    }
    // Style groups.
    for (i = 0; i < o.paragraphStyleGroups.length; i++) {
        // Recursive; calls itself.
        a = a.concat(getParagraphStyles(o.paragraphStyleGroups[i]));
    }
    return a;
}

 

 

William Campbell

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 11, 2022 May 11, 2022

Copy link to clipboard

Copied

Hi William, the API also has allParagraphStyles, allCharacterStyles, and allObjectStyles which return arrays (not collections) of all the document’s styles. Try this which gets all paragraph styles including styles in folders:

 

var aps = app.activeDocument.allParagraphStyles
var i = aps.length; 
while (i--) $.writeln(aps[i].name);

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
May 11, 2022 May 11, 2022

Copy link to clipboard

Copied

Nice. Missed that one. I will definitely put that to use. Thank you.

William Campbell

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 11, 2022 May 11, 2022

Copy link to clipboard

Copied

@LynxKx is using the Javascript window class, but for some dialogs I find the built-in dialog class is easier to code. Here’s the template I use for dropdowns, which includes functions for arrays (allParagraphStyles) and collections (PDFpresets) to get the dropdown lists.

 

 

makeDialog();


var psSel, pdfPreset;
function makeDialog(){
    var theDialog = app.dialogs.add({name:"Dialog Components", canCancel:true});
    with(theDialog){
        with(dialogColumns.add()){
                with(dialogColumns.add()){
                    staticTexts.add({staticLabel:"Paragraph Styles:"});
                    staticTexts.add({staticLabel:"PDF Presets:"});
                }
                with(dialogColumns.add()){
                    //array
                    psSel = dropdowns.add({stringList:getArrayNames(app.activeDocument.allParagraphStyles), selectedIndex:0, minWidth:80});
                    //Collection
                    pdfPreset = dropdowns.add({stringList:getCollection(app.pdfExportPresets), selectedIndex:3, minWidth:80});
                } 
        }
        if(theDialog.show() == true){
            psSel = app.activeDocument.allParagraphStyles[psSel.selectedIndex];
            pdfPreset = app.pdfExportPresets[pdfPreset.selectedIndex];
            main();
            theDialog.destroy();
        }
    }
}

function main(){
    alert("\rChosen Paragraph Style: " + psSel.name+ "\rChosen PDF Preset: " + pdfPreset.name);
    return 
}

/**
* Returns a list of style names from the provided array of styles. 
* Note does not work with a collection allParagraphStyles is an array paragraphStyles is a collection
* @ param the object array 
* @ return array of names 
*/
function getArrayNames(arr){
    var a = new Array;
    for(var i = 0; i < arr.length; i++){
        a.push(arr[i].name);
    }
    return a
}

/**
* Returns a list of item names from the provided collection.
* @param the collection 
* @return array of names 
*/
function getCollection(o){
    var a = new Array;
    for(var i = 0; i < o.length; i++){
        a.push(o.item(i).name);
    }
    return a
}

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 11, 2022 May 11, 2022

Copy link to clipboard

Copied

LATEST

Hi William,

and the best thing about allParagraphStyles, allCharacterStyles and allObjectStyles is:

 

The array's order of styles is the order of styles you see in the panel from top to bottom.

If the parent of a given style is the document the style is in the "root" of the style's panel.

If not, the parent of a style is a style group.

 

Regards,
Uwe Laubender

( ACP )

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines