Access to layers in onClick event handler
Copy link to clipboard
Copied
Hi. I'm trying to access all the layers in the current document when I click a button in a custom window that I am made. Here's my code so far:
var doc = app.activeDocument;
var palette = new Window("palette");
var button = palette.add("button", undefined, "Play");
palette.show();
button.onClick = function() {
var numLayers = doc.layers.length;
$.writeln(numLayers.toString());
};
The problem I am having is that the "layers" collection doesn't seem to exist in the active document when I try to access it in the onClick event. Perhaps there is something I don't understand about button event handlers?
Explore related tutorials & articles
Copy link to clipboard
Copied
This is because with palettes, this gets infinitely more complicated because you have to send the code as a string through the BridgeTalk object. See this thread for an explanation: Re: Calling functions from UI palette
Copy link to clipboard
Copied
Thanks Silly-V​. I was able to make illustrator send a message to itself. Here's the code if anyone else needs it:
#target illustrator
var loadCode = '$.writeln(app.activeDocument.layers.length);';
var animPalette = new Window("palette");
var button = animPalette.add("button", undefined, "Play");
animPalette.show();
// When button is clicked, create the BridgeTalk Object so we can send a message
// to an application (in this case its illustrator sending a message to itself)
button.onClick = function() {
var bt = new BridgeTalk;
bt.target = "illustrator";
bt.body = loadCode;
bt.send();
};
// Callback for when illustrator recieves the message
// We use eval to read the message string and evaluate it as JS code
BridgeTalk.onRecieve = function( message )
{
eval(message.body);
};
I'm curious though, is there a way to extract the script you want to run, into its own file as opposed to sending it as a string?
Copy link to clipboard
Copied
Hmm, I think using a palette, you have to send anything in a string regardless - but there may be more easier ways to do this.
You could, for example, try to send a simple message that points to a .jsx file and use the file.execute() on it.
In my case, I typically read in external .jsx files as text and send them through BT. There's a BridgeTalkEncode function floating around here, which is essential to ensure your script string stays intact and no comments or gotchas cause syntax errors.
Copy link to clipboard
Copied
Here's something I just threw together. This way of doing things allows you to encapsulate your logic in a method instead of writing it as a string. It still gets turned into a string when you send it to BridgeTalk but at least this way you don't have to write code in a nasty nasty string
// This method takes in a function
// and returns that function as a string + the function name and parenthesis
// so in the end it spits out a function declaration and invokation: "myMethod() {} myMethod()"
function strMethod(fn)
{
return fn.toString() + fn.name + "()";
}
// The method we want to "stringify"
function addLayer()
{
app.activeDocument.layers.add();
}
var message = strMethod(addLayer);
var animPalette = new Window("palette");
var button = animPalette.add("button", undefined, "Play");
animPalette.show();
// When button is clicked, create the BridgeTalk Object so we can send a message
// to an application (in this case its illustrator sending a message to itself)
button.onClick = function() {
var bt = new BridgeTalk;
bt.target = "illustrator";
bt.body = message;
bt.send();
};

