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

Contributor ,
Aug 07, 2022 Aug 07, 2022

Copy link to clipboard

Copied

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...

Screenshot 2022-08-07 at 16.43.47.png

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;
        }

 

TOPICS
Scripting

Views

70

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

correct answers 1 Correct answer

Advisor , Aug 07, 2022 Aug 07, 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.comp
...

Likes

Translate

Translate
Contributor ,
Aug 07, 2022 Aug 07, 2022

Copy link to clipboard

Copied

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

Screenshot 2022-08-07 at 16.52.34.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
Advisor ,
Aug 07, 2022 Aug 07, 2022

Copy link to clipboard

Copied

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);
        }
    }
}

 

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
Contributor ,
Aug 07, 2022 Aug 07, 2022

Copy link to clipboard

Copied

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. 

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
Advisor ,
Aug 07, 2022 Aug 07, 2022

Copy link to clipboard

Copied

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. 

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
Contributor ,
Aug 07, 2022 Aug 07, 2022

Copy link to clipboard

Copied

LATEST

That's great – I was getting an undefined object error in VSC but now it's gone. Integrating your script into a new one to check filenames first before changing colours.

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