Skip to main content
Inspiring
August 7, 2022
Answered

Javascript only fills one item from the selection with the correct colour

  • August 7, 2022
  • 1 reply
  • 429 views

Hi all,

I'm looking to change the fill colour of every selected item on an artboard.

This isn't the actual logo, just a mockup, but helps explain things...

The stars are grouped

UGH is outlined text (a compound path).

The black line is a rectangle

"Truly..." is editable text

"Wherever..." is also editable text.

 

I've been reading about compound paths being tricky to colour, but why is only one element being changed? My head hurts.

 

Can any kind soul help out?

 

var doc = app.activeDocument;
var ABs = doc.artboards;
ABs.setActiveArtboardIndex(178);
doc.selectObjectsOnActiveArtboard();

var setColor = new RGBColor();

 setColor.red = 90;
    setColor.green = 180;
    setColor.blue = 180;

    var pathItems = doc.selection;

        for (var i = 0; i < pathItems.length; i++) {
            pathItems[i].filled = true;
            pathItems[i].fillColor = setColor;
        }

 

This topic has been closed for replies.
Correct answer femkeblanco

I presume you want to color everything the same color.  The problem is that the "selection" collection consists of just the top level items, i.e. the first level in a hierarchy.  If there are nested items (groups and compound paths, which could be of any depth), the pathItems you want to color will be the last level in the hierarchy.  For example (these are just some possibilities)

 

// doc.pathItems[...].fillColor = setColor;
// doc.groupItems[...].pathItems[...].fillColor = setColor;
// doc.compoundPathItems[...].pathItems[...].fillColor = setColor;
// doc.groupItems[...].compoundPathItems[...].pathItems[...].fillColor = setColor;

 

The easier code to write, although it may be more difficult to visualise, uses recursion.  This also covers every possibility.  The alternative, if you know your hierarchy, would be a series of nested loops with a conditional before each loop testing for the item type.  The method with recursion is shown below.  For more on recursion, see here 

 

Text frames have their owen syntax:

 

// doc.textFrames[...].textRange.fillColor = setColor;

 

One last note:  "pathItems" is a name of a built-in collection.  Don't use it as a variable name.  Use "items" instead. 

 

var doc = app.activeDocument;
var ABs = doc.artboards;
ABs.setActiveArtboardIndex(178);
doc.selectObjectsOnActiveArtboard();

var setColor = new RGBColor();
setColor.red = 90;
setColor.green = 180;
setColor.blue = 180;

var items = doc.selection;
var array = [];
recurse(items);
for (var i = 0; i < array.length; i++) {
    array[i].filled = true;
    array[i].fillColor = setColor;  
}
function recurse(items) {
    for (var i = 0; i < items.length; i++) {
        if (items[i].typename == "TextFrame") {
            items[i].textRange.fillColor = setColor;
        } else if (items[i].typename == "PathItem") {
            array.push(items[i]);
        } else if (items[i].typename == "GroupItem") {
            recurse(items[i].pageItems);
        } else if (items[i].typename == "CompoundPathItem") {
            recurse(items[i].pathItems);
        }
    }
}

 

1 reply

JustyRAuthor
Inspiring
August 7, 2022

...this is what changes when the script is run...

femkeblanco
femkeblancoCorrect answer
Brainiac
August 7, 2022

I presume you want to color everything the same color.  The problem is that the "selection" collection consists of just the top level items, i.e. the first level in a hierarchy.  If there are nested items (groups and compound paths, which could be of any depth), the pathItems you want to color will be the last level in the hierarchy.  For example (these are just some possibilities)

 

// doc.pathItems[...].fillColor = setColor;
// doc.groupItems[...].pathItems[...].fillColor = setColor;
// doc.compoundPathItems[...].pathItems[...].fillColor = setColor;
// doc.groupItems[...].compoundPathItems[...].pathItems[...].fillColor = setColor;

 

The easier code to write, although it may be more difficult to visualise, uses recursion.  This also covers every possibility.  The alternative, if you know your hierarchy, would be a series of nested loops with a conditional before each loop testing for the item type.  The method with recursion is shown below.  For more on recursion, see here 

 

Text frames have their owen syntax:

 

// doc.textFrames[...].textRange.fillColor = setColor;

 

One last note:  "pathItems" is a name of a built-in collection.  Don't use it as a variable name.  Use "items" instead. 

 

var doc = app.activeDocument;
var ABs = doc.artboards;
ABs.setActiveArtboardIndex(178);
doc.selectObjectsOnActiveArtboard();

var setColor = new RGBColor();
setColor.red = 90;
setColor.green = 180;
setColor.blue = 180;

var items = doc.selection;
var array = [];
recurse(items);
for (var i = 0; i < array.length; i++) {
    array[i].filled = true;
    array[i].fillColor = setColor;  
}
function recurse(items) {
    for (var i = 0; i < items.length; i++) {
        if (items[i].typename == "TextFrame") {
            items[i].textRange.fillColor = setColor;
        } else if (items[i].typename == "PathItem") {
            array.push(items[i]);
        } else if (items[i].typename == "GroupItem") {
            recurse(items[i].pageItems);
        } else if (items[i].typename == "CompoundPathItem") {
            recurse(items[i].pathItems);
        }
    }
}

 

femkeblanco
Brainiac
August 7, 2022

Once again, thank you!

Your script was changing all text frames on all artboards, so I swapped this line:

    doc.textFrames[i].textRange.fillColor = setColor;

to this:

    doc.selection[i].textRange.fillColor = setColor;

 Now it works perfectly. 


My bad.  It was originally inside recurse(), but I took it out to make it look easier.  But two loops are unnecessary, so I've put it back in there.