Skip to content

Instantly share code, notes, and snippets.

@joshbduncan
Created January 20, 2023 21:43
Show Gist options
  • Save joshbduncan/be1e78f1e549f1ee4364de91c84d6c86 to your computer and use it in GitHub Desktop.
Save joshbduncan/be1e78f1e549f1ee4364de91c84d6c86 to your computer and use it in GitHub Desktop.
Go To Artboard (hacky example)
// Please note this is a hacky example in response to a question
// on the Adobe forums at the link below.
// https://community.adobe.com/t5/illustrator-discussions/using-artboards-as-an-archive-that-is-searchable/td-p/13504883
var aiVersion = parseFloat(app.version);
var locale = $.locale;
var os = $.os;
var sysOS = /mac/i.test(os) ? "mac" : "win";
var windowsFlickerFix = sysOS === "win" && aiVersion < 26.4 ? true : false;
var windowsFlickerFix = sysOS === "win" && aiVersion < 26.4 ? true : false;
var doc = app.activeDocument;
var artboards = {};
var artboardNames = [];
for (var i = 0; i < doc.artboards.length; i++) {
artboards[doc.artboards[i].name] = i;
artboardNames.push(doc.artboards[i].name);
}
var result = commandPalette(artboardNames, "Pick An Artboard", [0, 0, 600, 182]);
if (result) {
doc.artboards.setActiveArtboardIndex(artboards[result]);
app.executeMenuCommand("fitin");
}
function commandPalette(commands, title, bounds) {
// create the dialog
var win = new Window("dialog");
win.text = title;
win.alignChildren = "fill";
var q = win.add("edittext");
q.helpTip = "Search for commands, actions, and loaded scripts.";
// work-around to stop windows from flickering/flashing explorer
if (windowsFlickerFix) {
simulateKeypress("TAB", 1);
} else {
q.active = true;
}
// setup the commands listbox
var list = win.add("listbox", bounds, commands);
list.selection = 0;
// window buttons
var winButtons = win.add("group");
winButtons.orientation = "row";
winButtons.alignChildren = ["center", "center"];
var ok = winButtons.add("button", undefined, "OK");
ok.preferredSize.width = 100;
var cancel = winButtons.add("button", undefined, "Cancel", {
name: "cancel",
});
cancel.preferredSize.width = 100;
// as a query is typed update the list box
var frameStart = 0;
q.onChanging = function () {
frameStart = 0;
q = this.text;
matches = q === "" ? commands : scoreMatches(q, commands);
if (matches.length > 0) {
temp = win.add("listbox", list.bounds, matches);
// close window when double-clicking a selection
temp.onDoubleClick = function () {
if (list.selection) win.close(1);
};
win.remove(list);
list = temp;
list.selection = 0;
}
};
if (list.items.length > 0) {
/*
Move the listbox frame of visible items when using the
up and down arrow keys while in the `q` edittext.
One problem with this functionality is that when a listbox listitem
is selected via a script the API moves the visible "frame" of items
so that the new selection is at the top. This is not standard behavior,
and not even how the listbox behaves when you use the up and down keys inside
of the actual listbox.
*/
q.addEventListener("keydown", function (k) {
if (k.keyName == "Up") {
k.preventDefault();
if (list.selection.index > 0) {
list.selection = list.selection.index - 1;
if (list.selection.index < frameStart) frameStart--;
}
} else if (k.keyName == "Down") {
k.preventDefault();
if (list.selection.index < list.items.length) {
list.selection = list.selection.index + 1;
if (list.selection.index > frameStart + 9 - 1) {
if (frameStart < list.items.length - 9) {
frameStart++;
} else {
frameStart = frameStart;
}
}
}
}
/*
If a selection is made inside of the actual listbox frame by the user,
the API doesn't offer any way to know which part of the list is currently
visible in the listbox "frame". If the user was to re-enter the `q` edittext
and then hit an arrow key the above event listener will not work correctly so
I just move the next selection (be it up or down) to the middle of the "frame".
*/
if (
list.selection.index < frameStart ||
list.selection.index > frameStart + 9 - 1
)
frameStart = list.selection.index - Math.floor(9 / 2);
// move the frame by revealing the calculated `frameStart`
list.revealItem(frameStart);
});
}
// close window when double-clicking a selection
list.onDoubleClick = function () {
if (list.selection) win.close(1);
};
if (win.show() == 1) {
if (list.selection) {
return list.selection;
}
}
return false;
}
/**
* Score array items based on regex string match.
* @Param {String} q String to search for.
* @Param {Array} arr String items to search for.
* @Returns {Array} Matching items sorted by score.
*/
function scoreMatches(q, arr) {
var word;
var words = [];
var scores = {};
var words = q.split(" ");
for (var i = 0; i < arr.length; i++) {
var score = 0;
for (var n = 0; n < words.length; n++) {
word = words[n];
if (word != "" && arr[i].match("(?:^|\\s)(" + word + ")", "gi") != null) score++;
}
if (score > 0) scores[arr[i]] = score;
}
return sortKeysByValue(scores, "score", "name");
}
/**
* Sort object keys by their value.
* @Param {Object} obj Simple object with `key`: `value` pairs.
* @Returns {Array} Array of keys sorted by value.
*/
function sortKeysByValue(obj) {
var sorted = [];
for (var key in obj) {
for (var i = 0; i < sorted.length; i++) {
if (obj[key] > obj[sorted[i]]) break;
}
sorted.splice(i, 0, key);
}
return sorted;
}
/**
* Simulate a key press for Windows users.
*
* This function is in response to a known ScriptUI bug on Windows.
* You can read more about it in the GitHub issue linked below.
* https://github.com/joshbduncan/AiCommandPalette/issues/8
*
* Basically, on some Windows Ai versions, when a ScriptUI dialog is
* presented and the active attribute is set to true on a field, Windows
* will flash the Windows Explorer app quickly and then bring Ai back
* in focus with the dialog front and center. This is a terrible user
* experience so Sergey and I attempted to fix it the best we could.
*
* This clever solution was created by Sergey Osokin (https://github.com/creold)
*
* @Param {String} k Key to simulate.
* @Param {Number} n Number of times to simulate the keypress.
*/
function simulateKeypress(k, n) {
if (!n) n = 1;
try {
var f = setupFileObject(settingsFolder, "SimulateKeypress.vbs");
if (!f.exists) {
var data = 'Set WshShell = WScript.CreateObject("WScript.Shell")\n';
while (n--) {
data += 'WshShell.SendKeys "{' + k + '}"\n';
}
f.encoding = "UTF-8";
f.open("w");
f.write(data);
f.close();
}
f.execute();
} catch (e) {
$.writeln(e);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment