I am looking for some advice on some speed increases on my Adobe Illustrator (AI) script. Just so you know, the script runs fine and is at a decent speed (couple seconds to maybe a minute max for large files), but would like to speed it up further.
A couple things to note about how AI and ExtendScript(ES) (my IDE) works (that I have observed):
Using layer or layers as a variable seems to cause some issues (have not determined an exact cause but there were somethings not working when I was using it, I think it may be a reserved word) so instead I use 'currentLayer' or 'allLayers' instead.
I don't have access to many common javascript libraries (no indexOf or forEach).
For my recursive loop, I have tried two different ways to run it that would make it cleaner or faster, neither have worked. So not much hope of improvements there (it works fine so far).
Script description: This is a simple, yet complex script. Its primary purpose is to search the layers in a adobe illustrator file and find the match (of the inputted text). There is also options for exact search (exact string), or not, case sensitive search, or find without these specifications. I also have a sorting script that sorts the layers (not included) if anyone suggests a search that requires a sorted list.
Here is a document that has a lot (almost all) of the functions I can use with AI - Illustrator-Scripting-Reference-JavaScript.pdf
#target illustrator
if (app.documents.length > 0) {
var doc = app.activeDocument;
var docLayers = doc.layers;
var inputText;
var caseSense = false;
var exactWord = false;
var match = false;
var textSearch = false;
var allLayers = [];
var layerNames = [];
// Display GUI
startGUI();
// Main Search function
function startSearch(layers) {
match = false;
flattenLayersRecursive(layers);
searchLayers();
// When match is found, show dialog
if (match) {
alert("Found match!");
match = false;
} else {
alert("No match found.");
match = false;
}
}
// Recursive loop to search all layers in active document
function flattenLayersRecursive ( layers ) {
var length = layers.length;
var currentLayer ;
try {
for (var i = length; i--;) { //var i = length; i--; //var i = 0; i <= length; i++
currentLayer = layers[i];
var locked = currentLayer.locked;
var visible = currentLayer.visible;
if (visible == true || locked == false) {
checkLayerType(inputText, currentLayer);
// Search for sublayers, page items or group items
if (currentLayer.layers) {
flattenLayersRecursive(currentLayer.layers);
flattenLayersRecursive(currentLayer.groupItems);
flattenLayersRecursive(currentLayer.pathItems);
flattenLayersRecursive(currentLayer.compoundPathItems);
flattenLayersRecursive(currentLayer.symbolItems);
flattenLayersRecursive(currentLayer.textFrames);
}
}
}
} catch (error) {
logger (error);
}
}// end flattenLayersRecursive
// Search for match between input and layer name
function checkLayerType( currentLayer ) {
try {
if (inputText) {
var layerName = "";
var layerType = currentLayer.typename;
var searchIndex = -1;
var exact = false;
switch (layerType) {
default:
layerName = currentLayer.name;
searchIndex = findLayerName(inputText, layerName);
selectLayer(searchIndex, currentLayer, layerType)
break;
case "SymbolItem":
layerName = currentLayer.symbol.name;
searchIndex = findLayerName(inputText, layerName);
selectLayer(searchIndex, currentLayer, layerType)
break;
case "TextFrame":
layerName = currentLayer.contents;
searchIndex = findLayerName(inputText, layerName);
selectLayer(searchIndex, currentLayer, layerType)
break;
case "Layer":
layerName = currentLayer.name;
searchIndex = findLayerName(inputText, layerName);
selectLayer(searchIndex, currentLayer, layerType)
break;
} // end Switch
} // end inputText
} catch (error) {
logger(error);
}
} // end Search
function findLayerName(inputText, layerName) {
var searchIndex = -1;
var caseSensitive = caseSense;
var exact = exactWord;
if (caseSensitive) {
searchIndex = layerName.indexOf(inputText) ;
} else if (exact) {
if (layerName === inputText) {
searchIndex = 0;
}
} else {
searchIndex = layerName.toLowerCase().indexOf(inputText.toLowerCase());
}
return searchIndex;
}
function selectLayer(searchIndex, currentLayer, layerType) {
if ( searchIndex != -1 ) {
if (layerType != "Layer") {
currentLayer.selected = true;
match = true;
} else if (layerType == "Layer") {
currentLayer.hasSelectedArtwork = true;
//layer.selected = true;
match = true;
}
}
} // end selectLayer
// Display GUI
function startGUI() {
// Create Main Window
var win = new Window( "dialog", "Layer Search Selection", undefined );
// Enable use of 'Enter' key
win.addEventListener ("keydown", function(kd) {enter(kd) });
// Style for Main Window
win.orientation = "column";
win.alignChildren = ["fill", "fill"];
//win.preferredSize = [150, 350];
// Style for Search group
var searchGrp = win.add("panel", undefined, "Search Layers");
searchGrp.orientation = "column";
searchGrp.alignChildren = ["fill", "fill"];
var titleMsg = searchGrp.add ("statictext", undefined, "Layer name to search:");
var txt_Input = searchGrp.add("edittext { characters: 1, justify: 'center', active: true }");
txt_Input.helpTip = "Input letters to search";
// Search Button
var searchBtn = searchGrp.add("button", undefined, "Search");
searchBtn.helpTip = "Search from text items";
searchBtn.onClick = function() {
inputText = txt_Input.text;
startSearch(docLayers);
app.redraw();
}
// Use Enter key
function enter(k) {
if (k.keyName == "Enter") {
inputText = txt_Input.text;
startSearch(docLayers);
app.redraw();
}
}
// Listener for the input
txt_Input.onChanging = function() {
app.redraw();
}
// Options
var optionsGrp = win.add("panel", undefined, "Options");
optionsGrp.orientation = "row";
optionsGrp.margins = [10, 15, 10, 6];
optionsGrp.alignChildren = ["fill", "fill"];
// Radio button: Case Sensitive
var rdb_caseSensitive = optionsGrp.add ("radiobutton", undefined, "Match Case");
rdb_caseSensitive.helpTip = "Case sensitive search";
rdb_caseSensitive.value = false;
// Listener: Case Sensitive
rdb_caseSensitive.onClick = function() {
caseSense = rdb_caseSensitive.value;
app.redraw();
}
// Radio button: Exact Word
var rdb_exactWord = optionsGrp.add ("radiobutton", undefined, "Match Exact Word");
rdb_exactWord.helpTip = "Search exact word";
rdb_exactWord.value = false;
// Listener: Exact Word
rdb_exactWord.onClick = function() {
exactWord = rdb_exactWord.value;
app.redraw();
}
// Radio button: None
var chk_none = optionsGrp.add ("radiobutton", undefined, "None");
chk_none.helpTip = "Use no extra option";
chk_none.value = false;
// Radio button: None
chk_none.onClick = function() {
exactWord = false;
caseSense = false;
app.redraw();
}
// Style for Extra
var extraGrp = win.add("panel", undefined, "Extra");
extraGrp.orientation = "row";
extraGrp.alignChildren = ["fill", "fill"];
// Button: Deselect all
var btnDeselect = extraGrp.add('button', undefined, "Deselect All");
btnDeselect.helpTip = "Deselect All Objects";
btnDeselect.onClick = function () {
app.executeMenuCommand ('deselectall');
app.redraw();
};
// Close button
var quitBtn = win.add("button", undefined, "Close");
quitBtn.helpTip = "Press Esc to Close";
// Event listener for the quit button
quitBtn.onClick = function() {
win.close();
}
// Centering & Show Window
win.center();
win.show();
}// end startGUI
} else {
alert("You do not have any document opened!");
}