Skip to main content
Participant
April 23, 2010
Answered

Building a color chipper

  • April 23, 2010
  • 2 replies
  • 4057 views

I'm new to scripting was handed a tool that pulled ink sport colors and made chips and have been saddled with a hard task, and need some help.

I need to create a tool wich will;

  • look at a file with multiple pieces of artwork on multiple layers,
  • create one color chip for each of the fill colors of the objects on each layer without repeating a chip,
  • generate a text field next to the chip that pulls the name of the fill color for the chip from the swatches pallet,
  • then align the chips for each layer to the artwork on that layer so they make nice neat columns below the artwork.

I have been able to creat something that looks at the swatch pallet and generates color chips for each swatch, and then name them the swatch name but I'm having trouble with aligning them, having it run once for each layer, and limiting the chips created to only one per fill color of objects.

This is the working script I have made.

function chipperMod()
{
    this.windowRef = null;
}

chipperMod.prototype.run=function()
{

    var docRef=app.activeDocument;
    var swatchXAnchor=646;
    var swatchYAnchor=42;
   
    var win = new Window("dialog", "Chipper Mod", [200, 200, 380, 395]);
    this.windowRef=win;
   
    win.scmPanel=win.add("panel", [10, 10, 170, 150], "Template Size");
   
    win.scmPanel.ltrPort=win.scmPanel.add("radiobutton", [10, 10, 180, 30], "Letter - Portrait");
    win.scmPanel.ltrLand=win.scmPanel.add("radiobutton", [10, 40, 180, 60], "Letter - Landscape");
    win.scmPanel.tabPort=win.scmPanel.add("radiobutton", [10, 70, 180, 90], "Tabloid - Portrait");
    win.scmPanel.tabLand=win.scmPanel.add("radiobutton", [10, 100, 180, 120], "Tabloid - Landscape");
       
    win.scmPanel.tabLand.value=true; //automaticly checks tabloid
   
    win.scmPanel.ltrPort.onClick=win.scmPanel.ltrLand.onClick=win.scmPanel.tabPort.onClick=win.scmPanel.tabLand.onClick = function()
    {
        if(win.scmPanel.ltrPort.value)
        {
            swatchXAnchor=35;
            swatchYAnchor=72;
        }
        else if(win.scmPanel.ltrLand.value)
        {
            swatchXAnchor=35;
            swatchYAnchor=72;
        }
        else if(win.scmPanel.tabPort.value)
        {
            swatchXAnchor=35;
            swatchYAnchor=77;
        }
        else if(win.scmPanel.tabLand.value)
        {
            swatchXAnchor=646;
            swatchYAnchor=42;
        }
    }

    win.goBtn = win.add("button", [10, 160, 80, 175], "Chip It");
    win.goBtn.selected = true;
    win.noBtn = win.add("button", [100, 160, 170, 175], "Cancel");
   
    win.goBtn.onClick = function ()
    {
    for(i=docRef.swatches.length-1;i>=0;i--) // for i variable = # of inks used ; list length greater then 0 ; list length decreasing
    {
        var swatchesRef=docRef.swatches;
        var swatchesRefName=swatchesRef.name;
   
            var swatchGroup=docRef.groupItems.add();                     // adds a group
            var swatchBox=swatchGroup.pathItems.rectangle(swatchYAnchor, swatchXAnchor, 22, 15); // adds a 22x15 swatch at some ancor points bassed on paper chosen
            swatchBox.fillColor=docRef.swatches.getByName(swatchesRefName).color; //fills with swatch color
            swatchBox.stroked=true;
            swatchBox.strokeWidth=.5;
            swatchBox.strokeColor=new GrayColor();
            swatchBox.strokeColor.gray=50;
            var swatchLabelX= swatchBox.left+swatchBox.width+6;
            var swatchLabelY = swatchBox.top-7; //setting margins
            var swatchLabel = swatchGroup.textFrames.pointText([swatchLabelX,swatchLabelY]);
   
            swatchLabel.contents = swatchesRefName;
            swatchLabel.textRange.characterAttributes.size=8;
            swatchLabel.textRange.characterAttributes.fillColor=new GrayColor();
            swatchLabel.textRange.characterAttributes.fillColor.gray=50;
            swatchXAnchor+=(84);
       
    }//end for
    win.close();
    }

    win.noBtn.onClick = function ()
    {
        win.close();
    }

    win.show();
   
}

if(typeof(chipperMod_unitTest) == "undefined") // is equal to
{
    new chipperMod().run();
}

And this is how I have tryed to change it to compare the swatches to fill of path objects.

function chipperMod ()
{
    this.windowRef = null;
}

chipperMod.prototype.run=function()
{

    var docRef=app.activeDocument;
    var swatchXAnchor=646;
    var swatchYAnchor=42;
   
    var win = new Window("dialog", "Chipper Experiment", [200, 200, 380, 395]);
    this.windowRef=win;
   
    win.scmPanel=win.add("panel", [10, 10, 170, 150], "Template Size");
   
    win.scmPanel.ltrPort=win.scmPanel.add("radiobutton", [10, 10, 180, 30], "Letter - Portrait");
    win.scmPanel.ltrLand=win.scmPanel.add("radiobutton", [10, 40, 180, 60], "Letter - Landscape");
    win.scmPanel.tabPort=win.scmPanel.add("radiobutton", [10, 70, 180, 90], "Tabloid - Portrait");
    win.scmPanel.tabLand=win.scmPanel.add("radiobutton", [10, 100, 180, 120], "Tabloid - Landscape");
       
    win.scmPanel.tabLand.value=true; //automaticly checks tabloid
   
    win.scmPanel.ltrPort.onClick=win.scmPanel.ltrLand.onClick=win.scmPanel.tabPort.onClick=win.scmPanel.tabLand.onClick = function()
    {
        if(win.scmPanel.ltrPort.value)
        {
            swatchXAnchor=35;
            swatchYAnchor=72;
        }
        else if(win.scmPanel.ltrLand.value)
        {
            swatchXAnchor=35;
            swatchYAnchor=72;
        }
        else if(win.scmPanel.tabPort.value)
        {
            swatchXAnchor=35;
            swatchYAnchor=77;
        }
        else if(win.scmPanel.tabLand.value)
        {
            swatchXAnchor=646;
            swatchYAnchor=42;
        }
    }

    win.goBtn = win.add("button", [10, 160, 80, 175], "Chip It");
    win.goBtn.selected = true;
    win.noBtn = win.add("button", [100, 160, 170, 175], "Cancel");
   
   
    // I HATE THIS FUNCTION
    //
    //
    //
    // HATE!!!
    win.goBtn.onClick = function ()
    {
    for(i=docRef.swatches.length-1;i>=0;i--) // for i variable = # of swatches used -1; list length greater then 0 ; list length decreasing
    {
        var swatchesRef=docRef.swatches;
        var swatchesRefName=swatchesRef.name;
        for(ii=docRef.pathItems.length-1;ii>=0;ii--) // for ii variable = # of paths used -1; list length greater then 0 ; list length decreasing
        {
            var pathRef=docRef.pathItems[ii];
            docRef.groupItems.add();
            // problem seems to be this if
        if(docRef.swatches.getByName(swatchesRefName).color==pathRef.fillColor) // if the color of the swatch = the fill color of the path then
        {
            var swatchGroup=docRef.groupItems.add();                     // adds a group
            var swatchBox=swatchGroup.pathItems.rectangle(swatchYAnchor, swatchXAnchor, 22, 15); // adds a 22x15 swatch at some ancor points bassed on paper chosen
            swatchBox.fillColor=docRef.swatches.getByName(swatchesRefName).color; //fills with swatch color
            swatchBox.stroked=true;
            swatchBox.strokeWidth=.5;
            swatchBox.strokeColor=new GrayColor();
            swatchBox.strokeColor.gray=50;
            var swatchLabelX= swatchBox.left+swatchBox.width+6;
            var swatchLabelY = swatchBox.top-7; //setting margins
            var swatchLabel = swatchGroup.textFrames.pointText([swatchLabelX,swatchLabelY]);
   
            swatchLabel.contents = swatchesRefName;
            swatchLabel.textRange.characterAttributes.size=8;
            swatchLabel.textRange.characterAttributes.fillColor=new GrayColor();
            swatchLabel.textRange.characterAttributes.fillColor.gray=50;
            swatchXAnchor+=(84);
        }//end if
    }//end for
}
    win.close();
    }

    win.noBtn.onClick = function ()
    {
        win.close();
    }

    win.show();
   
}

if(typeof(chipperMod_unitTest) == "undefined") // is equal to
{
    new chipperMod().run();
}

Any help anyone can give me, would be much aprechiated. Maybe I have been going at this all wrong, I'm just not sure. I've tested the above and know it runs threw both of the loops and think that the problem is in  if(docRef.swatches.getByName(swatchesRefName).color==pathRef.fillColor) but even after I get that figured out I dont know how to make it not repeat making a chip unless its used on multiple layers. Or how to align them based on art in layers instead of just a place on the artboard. Thanks for reading and once again any help is apprechiated.

This topic has been closed for replies.
Correct answer artchrome

Hi Jwhar,

1) I suppose you work with RGB color

2)  docRef.swatches.getByName(swatchesRefName).color AND pathRef.fillColor  RETURN [RGBColor] not values

3) .toString() help to  compare docRef.swatches.getByName(swatchesRefName).color WITH  pathRef.fillColor, i don't why exactly but without it doesn't return  true when is really true , i suppose it compare [propertie] with [text], so  toString() convert it to [text] also..

4) if i  understand what you need , try this following script

#target illustrator
var docRef = app.activeDocument;
var iL=docRef.pathItems.length;
var Stored=new Array()
var swatchXAnchor=6;
    var swatchYAnchor=42;

for (i=0;i<iL;i++){
     myItem=docRef.pathItems;
     for (s=0;s<docRef.swatches.length;s++){
          
          if (docRef.swatches.color=="[RGBColor]"){ //implement only for RGB
     var r1=docRef.swatches.color.red
     var g1=docRef.swatches.color.green
     var b1=docRef.swatches.color.blue
     var r2=myItem.fillColor.red
     var g2=myItem.fillColor.green
     var b2=myItem.fillColor.blue
     if (r1==r2&&g1==g2&&b1==b2){
                    Stored=s; // avoid duplicate entry
                    }
               }
          }
     }
for (e=0;e<Stored.length;e++){
     if (Stored!=undefined){ // only if something
     var swatchesRefName=docRef.swatches[Stored].name;
    //var  swatchesValue=
            var swatchGroup=docRef.groupItems.add();                     // adds a group
            var swatchBox=swatchGroup.pathItems.rectangle(swatchYAnchor, swatchXAnchor, 22, 15); // adds a 22x15 swatch at some ancor points bassed on paper chosen
            swatchBox.fillColor=docRef.swatches[Stored].color; //fills with swatch color
            swatchBox.stroked=true;
            swatchBox.strokeWidth=.5;
            swatchBox.strokeColor=new GrayColor();
            swatchBox.strokeColor.gray=50;
            var swatchLabelX= swatchBox.left+swatchBox.width+6;
            var swatchLabelY = swatchBox.top-7; //setting margins
            var swatchLabel = swatchGroup.textFrames.pointText([swatchLabelX,swatchLabelY]);
  
            swatchLabel.contents = swatchesRefName;
            swatchLabel.textRange.characterAttributes.size=8;
            swatchLabel.textRange.characterAttributes.fillColor=new GrayColor();
            swatchLabel.textRange.characterAttributes.fillColor.gray=50;
            swatchXAnchor+=(84);
               }
     }

it make only new colored box if and only if swatches=path  color

See u, art.chrome

2 replies

artchrome
Inspiring
April 27, 2010

Hi,

there are few mistakes in your second script:

fisrt:

if(docRef.swatches.getByName(swatchesRefName).color==pathRef.fillColor)

each value return "[CMYKColor]"

So you compare if [CMYKColor]=[CMYKColor]... it's alway true

it's does't compare the value color

moreover this is line of code don't work but this following work

if(docRef.swatches.getByName(swatchesRefName).color.toString()==pathRef.fillColor)

second:

there is another problem:

for(i=docRef.swatches.length-1;i>=0;i--) // for i variable = # of swatches used -1; list length greater then 0 ; list length decreasing
    {
        var swatchesRef=docRef.swatches;
        var swatchesRefName=swatchesRef.name;
        for(ii=docRef.pathItems.length-1;ii>=0;ii--) // for ii variable = # of paths used -1; list length greater then 0 ; list length decreasing
        {
            var pathRef=docRef.pathItems[ii];
            docRef.groupItems.add();

each time i=i+1 there is one more pathRef:

docRef.groupItems.add()

so one pathRef to compare with swatches, but you don't need because it's previous rectangular colored box

becarfull:

imagine: first path is named "mypath"

mypath his index is 0

now you create new path named "mySecondPath"

now "mypath" have index 1

and "mySecondPath" have index 0

So, each time you compare pathRef/swatches  after new created path you risk to compare createdPath with swatches.

I think

1) Loop {compare (path/swatches) and store in Array() if true}

2) Loop {for each value's Array() create new colored path}

what do you think about it ? See U art.chrome

Jwhar26Author
Participant
April 27, 2010

The docRef.groupItems.add()was a test I put in and forgot to remove. I  was testing to make sure it ran both of the loops because I was getting  no results. By adding that I could figure out if it ran the appropriate  amount of times #of paths * #of swatches= new group items = # of times  script checked if statement. I totaly missed that I left that in there,  sorry for confushion it caused. It should be deleted.

So are you saying it returns the result [cmyk color] or [rgb color]  instead of result [c=50 m=15 y=45 k=10] or [r=5 g=40 b= 50] (I made up numbers for example only) if so how is if(docRef.swatches.getByName(swatchesRefName).color.toString()==pathRef.fillColor) any better because then your comparing

if [cmyk color] = [c=50 m=15 y=45 k=10] that would never be true, pathRef.fillColor could only = [rgb color] or [cmyk color] while the other side of the equation = [c= m= y= k=] or [r= g= b= ]

toString ()  string Returns the object type of a referenced object. If the object has a name, also returns the name.    *From JS Reference.*

I dont understand the toString() part very well. If they make a swatch and call it Random Red does swatches.getByName(swatchesRefName).color.toString()  return a cmyk value for that swatch? [c=10 m=85 y=15 k=10] or does it return [swatch, Random Red]

I want to compare the fill color of objects to the color of swatches. So if I have a swatch that is Named Dirty Yellow with values c=20 m=28 y=55 k=33 and no object has the same fill color  c=20 m=28 y=55 k=33 it does not make a color chip for it. If an object does have the same fill color I want it to generate a color chip and name it Dirty Yellow.

or to say it differently...

if swatch color (loop) needs to return [c= m= y= k= ]     =      object fill color (loop) needs to return [c= m= y= k= ]

then make chip named swatch color

if swatch color (loop)      !=    object fill color (loop)

then Do Not make chip named swatch color

this seems to be the same with an adition

I think

1) Loop {compare (path/swatches) and store in Array()  if true}

2) Loop {for each value's Array() create new colored  path}  and label path with swatch name

I'm starting simple and trying to get it to just work for paths for now. Later I will add compound paths also.

I hope we are both understanding each other correctly. Thanks for all your help!

artchrome
artchromeCorrect answer
Inspiring
April 28, 2010

Hi Jwhar,

1) I suppose you work with RGB color

2)  docRef.swatches.getByName(swatchesRefName).color AND pathRef.fillColor  RETURN [RGBColor] not values

3) .toString() help to  compare docRef.swatches.getByName(swatchesRefName).color WITH  pathRef.fillColor, i don't why exactly but without it doesn't return  true when is really true , i suppose it compare [propertie] with [text], so  toString() convert it to [text] also..

4) if i  understand what you need , try this following script

#target illustrator
var docRef = app.activeDocument;
var iL=docRef.pathItems.length;
var Stored=new Array()
var swatchXAnchor=6;
    var swatchYAnchor=42;

for (i=0;i<iL;i++){
     myItem=docRef.pathItems;
     for (s=0;s<docRef.swatches.length;s++){
          
          if (docRef.swatches.color=="[RGBColor]"){ //implement only for RGB
     var r1=docRef.swatches.color.red
     var g1=docRef.swatches.color.green
     var b1=docRef.swatches.color.blue
     var r2=myItem.fillColor.red
     var g2=myItem.fillColor.green
     var b2=myItem.fillColor.blue
     if (r1==r2&&g1==g2&&b1==b2){
                    Stored=s; // avoid duplicate entry
                    }
               }
          }
     }
for (e=0;e<Stored.length;e++){
     if (Stored!=undefined){ // only if something
     var swatchesRefName=docRef.swatches[Stored].name;
    //var  swatchesValue=
            var swatchGroup=docRef.groupItems.add();                     // adds a group
            var swatchBox=swatchGroup.pathItems.rectangle(swatchYAnchor, swatchXAnchor, 22, 15); // adds a 22x15 swatch at some ancor points bassed on paper chosen
            swatchBox.fillColor=docRef.swatches[Stored].color; //fills with swatch color
            swatchBox.stroked=true;
            swatchBox.strokeWidth=.5;
            swatchBox.strokeColor=new GrayColor();
            swatchBox.strokeColor.gray=50;
            var swatchLabelX= swatchBox.left+swatchBox.width+6;
            var swatchLabelY = swatchBox.top-7; //setting margins
            var swatchLabel = swatchGroup.textFrames.pointText([swatchLabelX,swatchLabelY]);
  
            swatchLabel.contents = swatchesRefName;
            swatchLabel.textRange.characterAttributes.size=8;
            swatchLabel.textRange.characterAttributes.fillColor=new GrayColor();
            swatchLabel.textRange.characterAttributes.fillColor.gray=50;
            swatchXAnchor+=(84);
               }
     }

it make only new colored box if and only if swatches=path  color

See u, art.chrome

artchrome
Inspiring
April 26, 2010

Hi Jwhar,

i don"t understand why you make dialogbox but you don't use it.. it should be have "return  (swatchXAnchor,swatchYAnchor)" after

else if(win.scmPanel.tabPort.value)
        {
           
swatchXAnchor=35;
            swatchYAnchor=77;
        }
      
else if(win.scmPanel.tabLand.value)
        {
           
swatchXAnchor=646;
            swatchYAnchor=42;
        }

// here put return of selected values ;)

Concerning dialog box , try lastest exemple of this : http://forums.adobe.com/thread/619085?tstart=0

but at this moment it's not really a problem

I think to another way:

1) put all path's/object's colors to swatches

2) put all swatches as colored rectangular object (like as you lmake in fisrt part of script)

... of course you can align each object at this moment in the script

Below an sample of my script tested with CS4 / MAC OS X

Some parts of code are not implemented cause i'have not time, i make it for simple CMYK object

#target illustrator
/////// Function /////////////
var MakeName=function(col){
     //alert(col);
     switch (col.toString()){
          
          case "[NoColor]":
          var named="NoColor";
          break;
          case "[GrayColor]":
          var named="GRAY"; //make your own implement
          break;
          case "[GradientColor]":
          var named="Gradient";
          break;
          case "[RVBColor]":
          Vr="R:"+col.red.toString().substr(0,4);
     Vv="V:"+col.green.toString().substr(0,4);
     Vb="B:"+col.blue.toString().substr(0,4);
     var named=Vr+Vv+Vb;
     break;
          case "[CMYKColor]":
     Vc="C:"+col.cyan.toString().substr(0,4);
     Vm="M:"+col.magenta.toString().substr(0,4);
     Vy="Y:"+col.yellow.toString().substr(0,4);
     Vb="B:"+col.black.toString().substr(0,4);
     var named=Vc+Vm+Vy+Vb;
     break;
     default:
     named="NoCaseImplemented";
     break;
}     
     
     return named;
     }

var MakeColor= function(pItem){
if (pItem.typename!="GroupItem"){
if (pItem.strokeColor!="[NoColor]"){
doc.swatches.add().color=pItem.strokeColor;
doc.swatches[doc.swatches.length-1].name=MakeName(pItem.strokeColor);
     }
if (pItem.fillColor!="[NoColor]"){
doc.swatches.add().color=pItem.fillColor;
doc.swatches[doc.swatches.length-1].name=MakeName(pItem.fillColor);
     }
}
}

///end Function //////

if ( app.documents.length > 0 && app.activeDocument.pathItems.length > 0) {

var doc=app.activeDocument;
var SI=doc.swatches.length-1;
for(i=0; i<doc.pathItems.length;i++){
MakeColor(doc.pathItems);
}
var NSI=doc.swatches.length-1;
}

var swatchXAnchor=6;
    var swatchYAnchor=42;
for(i=SI;i<NSI;i++) {
        var swatchesRef=docRef.swatches;
        var swatchesRefName=swatchesRef.name;
  
            var swatchGroup=docRef.groupItems.add();                     // adds a group
            var swatchBox=swatchGroup.pathItems.rectangle(swatchYAnchor, swatchXAnchor, 22, 15); // adds a 22x15 swatch at some ancor points bassed on paper chosen
            swatchBox.fillColor=docRef.swatches.getByName(swatchesRefName).color; //fills with swatch color
            swatchBox.stroked=true;
            swatchBox.strokeWidth=.5;
            swatchBox.strokeColor=new GrayColor();
            swatchBox.strokeColor.gray=50;
            var swatchLabelX= swatchBox.left+swatchBox.width+6;
            var swatchLabelY = swatchBox.top-7; //setting margins
            var swatchLabel = swatchGroup.textFrames.pointText([swatchLabelX,swatchLabelY]);
  
            swatchLabel.contents = swatchesRefName;
            swatchLabel.textRange.characterAttributes.size=8;
            swatchLabel.textRange.characterAttributes.fillColor=new GrayColor();
            swatchLabel.textRange.characterAttributes.fillColor.gray=50;
            swatchXAnchor+=(84);
      
    }//end for

note also, there aren't process to detect duplicated color

So.. i hope this can help you  a little

art.chrome

Jwhar26Author
Participant
April 26, 2010

Thanks for the reply.

The help with the dialoge box is understood but I'm going to need to spend some more time with the rest of your script. Right now I am not seeing how it solves any of my issues. Once again thank you for the reply though.