├── Ai Merge.jsx
├── Ai Sessions.jsx
├── Artboard Labels.jsx
├── Center on Artboards.jsx
├── Contact Sheet
├── .idea
│ ├── Contact Sheet.iml
│ ├── codeStyles
│ │ └── codeStyleConfig.xml
│ ├── encodings.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── vcs.xml
│ └── workspace.xml
├── Contact Sheet.jsx
├── FileList.js
├── Progress.js
├── backup
│ └── Contact Sheet.jsx
├── config.jsx
├── lang.jsx
└── work.js
├── Group Overlapping Objects.jsx
├── Helpers.jsx
├── IconJar to Artboards.jsx
├── Iterator.js
├── JSON.jsx
├── Merge SVG Docs.jsx
├── Progress.jsx
├── README.md
├── Resize All Artboards.jsx
├── SVG Exporter.jsx
├── Save Open Docs.jsx
├── ScriptPanel_2.jsx
├── Smart Layer Export.jsx
├── _string.scpt
├── bak-SVG Exporter.jsx
├── copy-layer-name-to-artboard.jsx
├── find-artboards-by-name.jsx
├── labels.js
├── polyfills.js
└── utils.jsx
/Ai Merge.jsx:
--------------------------------------------------------------------------------
1 | #target illustrator
2 | #include "~/github/iconify/ai-merge/Ai Merge.jsx";
--------------------------------------------------------------------------------
/Ai Sessions.jsx:
--------------------------------------------------------------------------------
1 | #target illustrator
2 | #include "~/github/iconify/ai-sessions/Ai Sessions.jsx";
--------------------------------------------------------------------------------
/Artboard Labels.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * ArtboardLabelsError object
3 | * @param message
4 | * @param stack
5 | * @constructor
6 | */
7 | var ArtboardLabelsError = function(message, stack) {
8 | this.message = message || 'Unknown ArtboardLabelsError';
9 | this.stack = stack || null;
10 | }
11 | ArtboardLabelsError.prototype = Error.prototype;
12 |
13 |
14 | /**
15 | * Create artboard labels.
16 | * @constructor
17 | */
18 | var ArtboardLabels = function() {
19 | if ( ! app.activeDocument) {
20 | alert(new ArtboardLabelsError("There are no open documents", $.stack));
21 | }
22 | else {
23 | var doc,
24 | artboard,
25 | artboards,
26 | theLabel;
27 |
28 | doc = app.activeDocument;
29 | artboards = doc.artboards;
30 |
31 | theLayer = doc.layers.add();
32 | theLayer.name = '__LABELS';
33 |
34 | doc.activeLayer = theLayer;
35 |
36 | for (var i = 0; i < app.activeDocument.artboards.length; i++) {
37 |
38 | doc.artboards.setActiveArtboardIndex(i);
39 |
40 | artboard = artboards[i];
41 |
42 | theLabel = doc.textFrames.add();
43 |
44 | theLabel.contents = artboard.name;
45 |
46 | theLabel.textRange.characterAttributes.size = 8;
47 |
48 | theLabel.position = [
49 | artboard.artboardRect[0],
50 | artboard.artboardRect[1] - (artboard.artboardRect[1] - (theLabel.height - 2))
51 | ];
52 | }
53 | }
54 | }
55 |
56 | new ArtboardLabels();
--------------------------------------------------------------------------------
/Center on Artboards.jsx:
--------------------------------------------------------------------------------
1 | #target Illustrator
#include "utils.jsx";
var CONFIG = {
LOGGING : true,
LOG_FOLDER : '~/Desktop/ai-logs/',
LOG_FILE_PATH : '~/Desktop/ai-logs/' + Utils.doDateFormat(new Date()) + '-log.txt',
};
var originalInteractionLevel = userInteractionLevel;
userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
if ( app.documents.length > 0) {
var doc = app.activeDocument;
Utils.showProgressBar(doc.artboards.length);
var interrupt = false;
app.executeMenuCommand("fitall");
var count = doc.artboards.length;
for (i = 0; i < count; i++) {
redraw();
// The interrupt is not working yet.
if (interrupt) break;
doc.artboards.setActiveArtboardIndex(i);
var activeAB = doc.artboards[doc.artboards.getActiveArtboardIndex()];
var right = activeAB.artboardRect[2];
var bottom = activeAB.artboardRect[3];
doc.selectObjectsOnActiveArtboard();
// If there are no visible items, update the progress bar and continue.
if (selection.length == 0) {
Utils.updateProgress('Artboard ' + i + ' has no visible items. Skipping.');
continue;
}
app.executeMenuCommand('group');
Utils.updateProgressMessage('Grouping selection');
/*
Utils.updateProgressMessage(
'Selection is ' + Utils.isVisibleAndUnlocked(selection) ? 'Visible' : 'Hidden'),
i + 1, doc.artboards.length
);
*/
for (x = 0 ; x < selection.length; x++) {
try {
if (! Utils.isVisibleAndUnlocked(selection)) continue;
selection[x].position = [
Math.round((right - selection[x].width)/2),
Math.round((bottom + selection[x].height)/2)
];
var scale = 105;
try {
selection[x].resize(scale, scale, true, true, true, true, scale);
}
catch(e) {
$.writeln("RESIZE ERROR : " + e);
}
}
catch(e) {
Utils.logger('ERROR - ' + e.message);
}
}
Utils.updateProgress('Selection centered');
}
Utils.progress.close();
redraw();
}
else {
alert("There are no open documents");
}
try {
userInteractionLevel = originalInteractionLevel;
}
catch(ex) {/*Exit Gracefully*/}
--------------------------------------------------------------------------------
/Contact Sheet/.idea/Contact Sheet.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Contact Sheet/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Contact Sheet/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Contact Sheet/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | JavaScript
23 |
24 |
25 |
26 |
27 | JavaScript
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Contact Sheet/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Contact Sheet/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Contact Sheet/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | /usr/local/bin/bower
36 |
37 |
38 |
39 | true
40 |
41 | false
42 | true
43 | true
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | 1570445261153
96 |
97 |
98 | 1570445261153
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/Contact Sheet/FileList.js:
--------------------------------------------------------------------------------
1 | /**
2 | * FileListError class.
3 | * @param message
4 | * @param stack
5 | * @constructor
6 | */
7 | var FileListError = function(message, stack) {
8 | this.name = "FileListError";
9 | this.message = message || "Unknown FileListError";
10 | this.stack = stack;
11 | };
12 | FileListError.prototype = Error.prototype;
13 |
14 | /**
15 | * File Extensions constants.
16 | * @type {{JPG: string, PDF: string, SVG: string, GIF: string, AI: string, PNG: string, EPS: string}}
17 | */
18 | var FileTypes = {
19 |
20 | SVG : "SVG",
21 | EPS : "EPS",
22 | AI : "AI",
23 | PDF : "PDF",
24 | PNG : "PNG",
25 | JPG : "JPG",
26 | GIF : "GIF",
27 |
28 | toRegex : function(theType) {
29 | if (typeof(FileTypes[theType.toUpperCase()]) == 'string') {
30 | return new RegExp(theType.toLowerCase(), 'ig');
31 | }
32 | }
33 | };
34 |
35 | /**
36 | * Class to get list of files. If you pass a file type or types array, the class
37 | * will return the list immediately. If you pass only the source folder, an interface
38 | * with several methods is returned.
39 | * @param rootFolder
40 | * @param fileTypes
41 | * @returns {*}
42 | * @constructor
43 | */
44 | var FileList = function(rootFolder, fileTypes) {
45 |
46 | if (typeof rootFolder == 'string') {
47 | rootFolder = new Folder(rootFolder);
48 | }
49 |
50 | if (typeof fileTypes != 'undefined') {
51 | return _getFiles(true, fileTypes);
52 | }
53 |
54 | /**
55 | * Get all files in subfolders.
56 | * @param {Folder} srcFolder The root folder from which to merge SVGs.
57 | * @returns {Array} Array of nested files.
58 | */
59 | function getFilesInSubfolders( srcFolder, recurse, fileTypes ) {
60 |
61 | if (typeof recurse != 'boolean') {
62 | recurse = false;
63 | }
64 |
65 | if (typeof fileTypes == 'string') {
66 | fileTypes = [fileTypes];
67 | }
68 |
69 | if ( ! (srcFolder instanceof Folder)) return;
70 |
71 | var theFolders = getSubFolders(srcFolder),
72 | theFileList = getFilesInFolder(srcFolder, fileTypes);
73 |
74 | if (! recurse || theFolders.length == 0) {
75 | theFileList = Array.prototype.concat.apply([], getFilesInFolder(srcFolder, fileTypes));
76 | }
77 | else {
78 | for (var x=0; x < theFolders.length; x++) {
79 | theFileList = Array.prototype.concat.apply(theFileList, getFilesInFolder(theFolders[x], fileTypes));
80 | }
81 | }
82 |
83 | return theFileList;
84 | }
85 |
86 | /**
87 | * Get all nested subfolders in theFolder.
88 | * @param theFolder
89 | * @returns {*}
90 | */
91 | function getSubFolders(theFolder) {
92 | var subFolders = [];
93 | var myFileList = theFolder.getFiles();
94 | for (var i = 0; i < myFileList.length; i++) {
95 | var myFile = myFileList[i];
96 | if (myFile instanceof Folder) {
97 | subFolders.push(myFile);
98 | subFolders = Array.prototype.concat.apply(
99 | subFolders,
100 | getSubFolders(myFile)
101 | );
102 | }
103 | }
104 | return subFolders;
105 | }
106 |
107 | /**
108 | * Gets the files in a specific source folder.
109 | *
110 | * NOTE: You may notice that in the code below we do not use the Illustrator File method
111 | * `theFolder.getFiles(/\.svg$/i)` to scan the folder for a specific file type, even though
112 | * it would be more efficient. The reason is that from time-to-time the MacOS will not correctly
113 | * identify the file type and the list comes back empty when it is, in fact, not empty. To prevent
114 | * the script from randomly stop working and require a system restart, we use a slightly less
115 | * efficient but more reliable method to identify the file extension.
116 | *
117 | * @param {Folder} The folder object
118 | * @returns {Array}
119 | */
120 | function getFilesInFolder(theFolder, fileTypes) {
121 |
122 | var theFile,
123 | theExt,
124 | fileList = [];
125 |
126 | // Make sure we are working with an array if a type is provided.
127 |
128 | if (typeof fileTypes == 'string') {
129 | fileTypes = [fileTypes];
130 | }
131 |
132 | fileList = theFolder.getFiles();
133 |
134 | if (typeof fileTypes.length != 'undefined' && fileTypes.length > 0) {
135 | var filtered = [];
136 | for (var t = 0; t < fileTypes.length; t++) {
137 | var fileType = fileTypes[t];
138 |
139 | for (var i = 0; i < fileList.length; i++) {
140 |
141 | theFile = fileList[i];
142 | theExt = theFile.name.split(".").pop();
143 |
144 | if ( theExt.trim().toUpperCase() == fileType.trim().toUpperCase() ) {
145 | filtered.push(theFile);
146 | }
147 | }
148 | }
149 | fileList = filtered;
150 | }
151 |
152 | return fileList;
153 | }
154 |
155 | /**
156 | * Get the file type from file extension.
157 | * @param theFile
158 | * @returns {string}
159 | */
160 | function getFileType(theFile) {
161 | return theFile.name.split(".").pop().trim().toUpperCase();
162 | }
163 |
164 | /**
165 | * List files except excluded types.
166 | * @param rootFolder
167 | * @param recurse
168 | * @param exclude
169 | * @returns {any}
170 | */
171 | function getAllFilesExcept(rootFolder, recurse, exclude) {
172 |
173 | if (typeof exclude == 'undefineed') {
174 | return new Error('Array of excluded types required in FileList.getAllFilesExcept');
175 | }
176 |
177 | var files = getFilesInSubfolders(rootFolder, recurse);
178 |
179 | var filtered = [];
180 | for (var i = 0; i < files.length; i++) {
181 | if (excluded.indexOf( getFileType(files[i]) ) == -1) {
182 | filtered.push(files[i]);
183 | }
184 | }
185 | return filtered;
186 | }
187 |
188 | /**
189 | * Get the file list.
190 | * @param recurse
191 | * @param fileTypes
192 | * @returns {Array}
193 | * @private
194 | */
195 | function _getFiles(recurse, fileTypes) {
196 | if (typeof recurse != 'boolean') recurse = false;
197 | return getFilesInSubfolders(rootFolder, recurse, fileTypes);
198 | }
199 |
200 | /**
201 | * Public interface.
202 | */
203 | return {
204 | getFiles : function(recurse, fileTypes) {
205 | return _getFiles(recurse, fileTypes);
206 | },
207 | getAllFilesExcept : function(recurse, excludeTypes) {
208 | return getAllFilesExcept(rootFolder, recurse, excludeTypes);
209 | },
210 | getFolders : function(recurse) {
211 | if (typeof recurse != 'boolean') recurse = false;
212 | return getSubFolders(recurse);
213 | }
214 | }
215 | };
216 |
--------------------------------------------------------------------------------
/Contact Sheet/Progress.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 Scott Lewis
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | */
25 |
26 | /**
27 | * The base Progress class.
28 | * @constructor
29 | */
30 | function Progress( options, show ) {
31 |
32 | this.top = 0;
33 | this.left = 0;
34 | this.width = 450;
35 | this.height = 130;
36 |
37 | this.minvalue = 0;
38 | this.maxvalue = 100;
39 |
40 | this.label = "";
41 |
42 | this.window = null;
43 | this.panel = null;
44 |
45 | if ( typeof(options) != "undefined" ) {
46 | for (key in options) {
47 | if (this.hasOwnProperty(key)) {
48 | this[key] = options[key];
49 | }
50 | }
51 | this.init( this.minvalue, this.maxvalue, this.label );
52 | }
53 |
54 | if (show) this.show();
55 | }
56 |
57 | /**
58 | * Initialize start settings.
59 | * @param {integer} start
60 | * @param {integer} end
61 | */
62 | Progress.prototype.init = function(start, end, message) {
63 |
64 | var top = 0,
65 | right = 0,
66 | bottom = 0,
67 | left = 0;
68 |
69 | try {
70 | this.minvalue = start;
71 | this.maxvalue = end;
72 | this.label = message;
73 |
74 | this.top = 0;
75 | this.left = 0;
76 | this.width = 450;
77 | this.height = 140;
78 |
79 | if ( bounds = getScreenSize() ) {
80 | left = Math.abs(Math.ceil((bounds.width/2) - (this.width/2)));
81 | top = Math.abs(Math.ceil((bounds.height/2) - (this.height/2)));
82 | }
83 |
84 | this.window = new Window(
85 | 'palette',
86 | 'Progress',
87 | [left, top, left + this.width, top + this.height]
88 | );
89 |
90 | this.window.pnl = this.window.add(
91 | 'panel',
92 | [10, 10, 440, 130],
93 | 'Progress'
94 | );
95 |
96 | this.window.pnl.progBar = this.window.pnl.add(
97 | 'progressbar',
98 | [20, 65, 410, 90],
99 | 0,
100 | this.maxvalue
101 | );
102 |
103 | this.window.pnl.progBarLabel = this.window.pnl.add(
104 | 'statictext',
105 | [20, 20, 410, 35],
106 | "Item 0 of " + this.maxvalue
107 | );
108 |
109 | this.window.pnl.progBarLabel2 = this.window.pnl.add(
110 | 'statictext',
111 | [20, 35, 410, 60],
112 | (typeof(this.label) != "undefined" ? " " + this.label : "" )
113 | );
114 | }
115 | catch(e) {alert(e)}
116 |
117 | function getScreenSize() {
118 | var screen;
119 |
120 | for (i=0; i<$.screens.length; i++) {
121 | if ($.screens[i].primary == true) {
122 | screen = $.screens[i];
123 | screen.width = screen.right - screen.left;
124 | screen.height = screen.bottom - screen.top;
125 | }
126 | }
127 | return screen;
128 | }
129 |
130 | return this;
131 | };
132 |
133 | /**
134 | * Show the progress bar.
135 | */
136 | Progress.prototype.show = function() {
137 | try { this.close(); } catch(e){};
138 | this.window.show();
139 |
140 | return this;
141 | };
142 |
143 | /**
144 | * Update the progress bar message & counter values.
145 | * @param {string} theMessage
146 | */
147 | Progress.prototype.update = function( theMessage ) {
148 |
149 | this.increment();
150 |
151 | this.text( 'Item ' + this.value() + ' of ' + this.max(), theMessage );
152 |
153 | $.sleep(10);
154 | this.window.update();
155 |
156 | return this;
157 | };
158 |
159 | /**
160 | * Set or get the progress text.
161 | * @param {string} theValue
162 | * @returns {*}
163 | */
164 | Progress.prototype.text = function( firstLine, secondLine ) {
165 | if (typeof(firstLine) != "undefined") {
166 | this.window.pnl.progBarLabel.text = firstLine;
167 | }
168 | if (typeof(secondLine) != "undefined") {
169 | this.window.pnl.progBarLabel2.text = secondLine;
170 | }
171 | return this.window.pnl.progBarLabel.text +
172 | this.window.pnl.progBarLabel2.text;
173 | };
174 |
175 | /**
176 | * Set or get the progress current value.
177 | * @param {integer} theValue
178 | * @returns {*}
179 | */
180 | Progress.prototype.value = function( theValue ) {
181 | if (typeof(theValue) != "undefined") {
182 | this.window.pnl.progBar.value = theValue;
183 | }
184 | return this.window.pnl.progBar.value;
185 | };
186 |
187 | /**
188 | * Get or set the minimum value.
189 | * @param {integer} theValue
190 | */
191 | Progress.prototype.min = function( theValue ) {
192 | if (typeof(theValue) != "undefined") {
193 | this.window.pnl.progBar.minvalue = theValue;
194 | }
195 | this.window.pnl.progBar.minvalue;
196 |
197 | return this;
198 | };
199 |
200 | /**
201 | * Get or set the maximum value.
202 | * @param {integer} theValue
203 | * @returns {number|integer|*}
204 | */
205 | Progress.prototype.max = function( theValue ) {
206 | if (typeof(theValue) != "undefined") {
207 | this.window.pnl.progBar.maxvalue = theValue;
208 | }
209 | return this.window.pnl.progBar.maxvalue;
210 | };
211 |
212 | /**
213 | * Increment the counter value.
214 | * @returns {*}
215 | */
216 | Progress.prototype.increment = function() {
217 | this.window.pnl.progBar.value++;
218 | return this.window.pnl.progBar.value;
219 | };
220 |
221 | /**
222 | * Close the progress bar.
223 | */
224 | Progress.prototype.close = function() {
225 | this.window.close();
226 | };
227 |
--------------------------------------------------------------------------------
/Contact Sheet/backup/Contact Sheet.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 Iconfinder
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | */
25 |
26 | /**
27 | * @author Iconfinder
28 | * @date 2017-02-04
29 | *
30 | * Installation:
31 | *
32 | * 1. Copy this file to Illustrator > Presets > Scripting
33 | * 2. Restart Adobe Illustrator
34 | * 3. Go to File > Scripts > Contact Sheet
35 | * 4. Follow the prompts
36 | *
37 | * Usage:
38 | *
39 | * This script will create a contact sheet of vector objects from a folder structure
40 | * that you specify. The resulting contact sheet will have margins that are calculated
41 | * thus: subtracting Left & Right Margins = (Page Width - Column Width * Column Count) / 2
42 | * Top & Bottom Margins = (Page Height - Row Height * Row Count) / 2
43 | */
44 |
45 | #target Illustrator
46 |
47 | #include "../utils.jsx";
48 |
49 | if (typeof(Utils) != 'object') {
50 | alert('Missing required class Utils (/Adobe Illustrator/presets/en_us/scripts/utils.jsx)');
51 | }
52 |
53 | #include "config.jsx";
54 |
55 | if (typeof(CONFIG) != 'object') {
56 | alert('Missing required class CONFIG (/Adobe Illustrator/presets/en_us/scripts/Contact Sheet/config.jsx)');
57 | }
58 |
59 | #include "lang.jsx";
60 |
61 | if (typeof(LANG) != 'object') {
62 | alert('Missing required class LANG (/Adobe Illustrator/presets/en_us/scripts/Contact Sheet/lang.jsx)');
63 | }
64 |
65 | var originalInteractionLevel = userInteractionLevel;
66 | userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
67 |
68 | /**
69 | * Displays the settings dialog
70 | *
71 | * Inputs:
72 | * - page width
73 | * - page height
74 | * - cell width
75 | * - cell height
76 | * - scale
77 | * - logging enabled
78 | *
79 | * - number of cols = divide page width by cell width
80 | * - number of rows = divide page height by cell height
81 | * - side margins = (page width - (col count * col width))/2
82 | * - top/bottom margins = (page height - (row count * row width))/2
83 | *
84 | * @return boolean|Settings object
85 | */
86 | function doDisplayDialog() {
87 |
88 | var response, dialog;
89 |
90 | var dialogWidth = 450;
91 | var dialogHeight = 410;
92 | var dialogLeft = 550;
93 | var dialogTop = 300;
94 |
95 | if ( bounds = Utils.getScreenSize() ) {
96 | dialogLeft = Math.abs(Math.ceil((bounds.width/2) - (dialogWidth/2)));
97 | // dialogTop = Math.abs(Math.ceil((bounds.height) - (dialogHeight/2)));
98 | }
99 |
100 | response = false;
101 |
102 | /**
103 | * Dialog bounds: [ Left, TOP, RIGHT, BOTTOM ]
104 | * default: //550, 350, 1000, 800
105 | */
106 |
107 | dialog = new Window(
108 | "dialog", LANG.LABEL_DIALOG_WINDOW, [
109 | dialogLeft,
110 | dialogTop,
111 | dialogLeft + dialogWidth,
112 | dialogTop + dialogHeight
113 | ]
114 | );
115 |
116 | try {
117 |
118 | var c1 = 28;
119 | var c1w = c1 + 112;
120 |
121 | var c2 = 142;
122 | var c2w = c2 + 50;
123 |
124 | var p1 = 16;
125 | var p2 = dialogWidth - 16;
126 | var p3 = (dialogWidth / 2 ) - 16
127 | var p4 = p3 + 16
128 | var p5 = p4 + p3;
129 |
130 | var r1 = 40;
131 |
132 | dialog.sizePanel = dialog.add('panel', [p1, 16, p3, 200], LANG.LABEL_SIZE);
133 | dialog.presetsPanel = dialog.add('panel', [p4, 16, p5, 200], LANG.LABEL_PRESETS);
134 | dialog.outputPanel = dialog.add('panel', [p1, 200, p2, 290], LANG.LABEL_OUTPUT);
135 | dialog.sourcePanel = dialog.add('panel', [p1, 290, p2, 350], LANG.LABEL_INPUT);
136 |
137 | dialog.pageWidthLabel = dialog.add("statictext", [c1, r1, c1w, 70], LANG.LABEL_PG_WIDTH);
138 | dialog.pageWidth = dialog.add("edittext", [c2, r1, c2w, 70], CONFIG.PG_WIDTH);
139 | dialog.pageWidth.active = true;
140 |
141 | dialog.pageHeightLabel = dialog.add("statictext", [c1, 70, c1w, 100], LANG.LABEL_PG_HEIGHT);
142 | dialog.pageHeight = dialog.add("edittext", [c2, 70, c2w, 100], CONFIG.PG_HEIGHT);
143 | dialog.pageHeight.active = true;
144 |
145 | dialog.colsLabel = dialog.add("statictext", [c1, 100, c1w, 130], LANG.LABEL_COL_COUNT);
146 | dialog.cols = dialog.add("edittext", [c2, 100, c2w, 130], CONFIG.COLS);
147 | dialog.cols.active = true;
148 |
149 | dialog.rowsLabel = dialog.add("statictext", [c1, 130, c1w, 160], LANG.LABEL_ROW_COUNT);
150 | dialog.rows = dialog.add("edittext", [c2, 130, c2w, 160], CONFIG.ROWS);
151 | dialog.rows.active = true;
152 |
153 | dialog.scaleLabel = dialog.add('statictext', [c1, 160, c1w, 190], LANG.LABEL_SCALE);
154 | dialog.scale = dialog.add('edittext', [c2, 160, c2w, 190], CONFIG.SCALE);
155 | dialog.scale.active = true;
156 |
157 | dialog.filenameLabel = dialog.add('statictext', [c1, 220, c1w, 250], LANG.LABEL_FILE_NAME);
158 | dialog.filename = dialog.add('edittext', [c2, 220, 334, 250], '');
159 | dialog.filename.active = true;
160 |
161 | dialog.logging = dialog.add('checkbox', [c1, 260, c1w, 330], LANG.LABEL_LOGGING);
162 | dialog.logging.value = CONFIG.LOGGING;
163 |
164 | dialog.folderBtn = dialog.add('button', [c1, 310, c1w, 340], LANG.LABEL_CHOOSE_FOLDER, {name: 'folder'});
165 |
166 | dialog.srcFolder = dialog.add('edittext', [140, 310, 424, 340], '');
167 | dialog.srcFolder.active = false;
168 |
169 | dialog.presets = dialog.add("listbox", [p4 + 16, 48, p5 - 16, 184]);
170 |
171 | dialog.cancelBtn = dialog.add('button', [232, 360, 332, 390], LANG.BUTTON_CANCEL, {name: 'cancel'});
172 | dialog.openBtn = dialog.add('button', [334, 360, 434, 390], LANG.BUTTON_OK, {name: 'ok'});
173 | dialog.saveBtn = dialog.add('button', [p1, 360, p1 + 120, 390], LANG.BUTTON_SAVE, {name: 'save'});
174 |
175 | initPresetsList(dialog);
176 | initButtons();
177 |
178 | dialog.setOutputFilename = function() {
179 | dialog.filename.text = "contact-" + CONFIG.PG_WIDTH + "x" + CONFIG.COLS + "x" + CONFIG.ROWS + "@" + CONFIG.SCALE + ".ai";
180 | CONFIG.OUTPUT_FILENAME = dialog.filename.text;
181 | }
182 |
183 | dialog.setOutputFilename();
184 |
185 | function updateConfig() {
186 |
187 | CONFIG.PG_WIDTH = parseInt(dialog.pageWidth.text);
188 | CONFIG.PG_HEIGHT = parseInt(dialog.pageHeight.text);
189 | CONFIG.LOGGING = dialog.logging.value;
190 | CONFIG.SCALE = parseInt(dialog.scale.text);
191 | CONFIG.COLS = parseInt(dialog.cols.text);
192 | CONFIG.ROWS = parseInt(dialog.rows.text);
193 | CONFIG.COL_WIDTH = parseInt((CONFIG.PG_WIDTH - (CONFIG.HOFF * 2)) / CONFIG.COLS);
194 | CONFIG.ROW_HEIGHT = parseInt((CONFIG.PG_HEIGHT - (CONFIG.VOFF * 2)) / CONFIG.ROWS);
195 | CONFIG.FRM_WIDTH = CONFIG.COL_WIDTH;
196 | CONFIG.FRM_HEIGHT = CONFIG.ROW_HEIGHT;
197 | CONFIG.OUTPUT_FILENAME = dialog.filename.text;
198 | }
199 | dialog.updateConfig = function() {
200 | updateConfig();
201 | }
202 |
203 | function initButtons() {
204 |
205 | dialog.saveBtn.enabled = false;
206 | dialog.openBtn.enabled = false;
207 |
208 | if (Utils.trim(dialog.pageWidth.text) == "") return;
209 | if (Utils.trim(dialog.pageHeight.text) == "") return;
210 | if (Utils.trim(dialog.cols.text) == "") return;
211 | if (Utils.trim(dialog.rows.text) == "") return;
212 | if (Utils.trim(dialog.scale.text) == "") return;
213 | if (parseInt(dialog.pageWidth.text) < 10 ) return;
214 | if (parseInt(dialog.pageHeight.text) < 10 ) return;
215 | if (parseInt(dialog.cols.text) < 1 ) return;
216 | if (parseInt(dialog.rows.text) < 1 ) return;
217 | if (parseInt(dialog.scale.text) < 1 ) return;
218 |
219 | dialog.saveBtn.enabled = true;
220 |
221 | if (Utils.trim(dialog.filename.text) == "") return;
222 | if (Utils.trim(dialog.srcFolder.text) == "") return;
223 |
224 | var testFolder = new Folder(dialog.srcFolder.text);
225 | // if (! testFolder.exists) return;
226 |
227 | dialog.openBtn.enabled = true;
228 | }
229 | dialog.initButtons = function() {
230 | initButtons();
231 | }
232 |
233 | dialog.pageWidth.onChange = function() {
234 | CONFIG.PG_WIDTH = dialog.pageWidth.text;
235 | initButtons();
236 | dialog.setOutputFilename();
237 | }
238 |
239 | dialog.cols.onChange = function() {
240 | CONFIG.COLS = dialog.cols.text;
241 | initButtons();
242 | dialog.setOutputFilename();
243 | }
244 |
245 | dialog.rows.onChange = function() {
246 | CONFIG.ROWS = dialog.rows.text;
247 | initButtons();
248 | dialog.setOutputFilename();
249 | }
250 |
251 | dialog.scale.onChange = function() {
252 | CONFIG.SCALE = dialog.scale.text;
253 | initButtons();
254 | dialog.setOutputFilename();
255 | }
256 |
257 | dialog.pageHeight.onChange = initButtons;
258 | dialog.filename.onChange = initButtons;
259 | dialog.srcFolder.onChange = initButtons;
260 |
261 | dialog.cancelBtn.onClick = function() {
262 | dialog.close();
263 | response = false;
264 | return false;
265 | };
266 |
267 | dialog.saveBtn.onClick = function() {
268 |
269 | updateConfig();
270 | savePresetsFile(CONFIG);
271 | initPresetsList(dialog);
272 | initButtons();
273 | };
274 |
275 | dialog.folderBtn.onClick = function() {
276 | var srcFolder;
277 | if ( srcFolder = Folder.selectDialog( CONFIG.CHOOSE_FOLDER ) ) {
278 |
279 | if ( srcFolder.fs == 'Windows' ) {
280 | CONFIG.PATH_SEPATATOR = "\\"
281 | }
282 |
283 | dialog.srcFolder.text = srcFolder.path + CONFIG.PATH_SEPATATOR + srcFolder.name;
284 | CONFIG.SRC_FOLDER = srcFolder;
285 |
286 | if ( Utils.trim(dialog.filename.text) == '' ) {
287 | // dialog.filename.text = srcFolder.name + '-contact-sheet.ai';
288 |
289 | setOutputFilename();
290 |
291 | CONFIG.OUTPUT_FILENAME = dialog.filename.text;
292 | }
293 | initButtons();
294 | }
295 | };
296 |
297 | dialog.openBtn.onClick = function() {
298 |
299 | updateConfig();
300 |
301 | dialog.close();
302 | response = true;
303 | return true;
304 | };
305 |
306 | dialog.show();
307 | }
308 | catch(ex) {
309 | Utils.logger('doDisplayDialog - ' + ex);
310 | }
311 | return response;
312 | }
313 |
314 | /**
315 | * Saves presets to JSON file.
316 | * @param {object} presets Presets object
317 | */
318 | function savePresetsFile(presets) {
319 | var filename = presets.PG_WIDTH + "x" + presets.PG_HEIGHT + "@" + presets.SCALE + ".json";
320 | Utils.write_json_file(
321 | CONFIG.PRESETS_FOLDER + "/" + filename, {
322 | "PG_WIDTH" : presets.PG_WIDTH,
323 | "PG_HEIGHT" : presets.PG_HEIGHT,
324 | "COLS" : presets.COLS,
325 | "ROWS" : presets.ROWS,
326 | "SCALE" : presets.SCALE
327 | }, true
328 | );
329 | }
330 |
331 | /**
332 | * Initialize the presets select list
333 | * @param dialog
334 | */
335 | function initPresetsList(dialog) {
336 |
337 | var presets, presetsFolder;
338 |
339 | try {
340 | presetsFolder = Utils.folder( CONFIG.PRESETS_FOLDER );
341 |
342 | if (presets = presetsFolder.getFiles("*.json")) {
343 |
344 | if (dialog.presets) {
345 | dialog.presets.removeAll();
346 | }
347 |
348 | for (var i=0; i rowCount ? rowCount : CONFIG.ROWS ;
462 |
463 | for (var rowCounter = 1 ; rowCounter <= rowCount; rowCounter++) {
464 |
465 | myY1 = bounds[1] + CONFIG.VOFF + (myRowHeight * (rowCounter-1));
466 | myY2 = myY1 + CONFIG.FRM_HEIGHT;
467 |
468 | /**
469 | * loop through columns
470 | * @type {Number}
471 | */
472 |
473 | colCount = CONFIG.COLS;
474 |
475 | if (rowCounter > 1) {
476 |
477 | var remaining = Math.ceil(srcFileList.length - i);
478 | if (remaining < colCount) {
479 | colCount = remaining;
480 | }
481 | }
482 |
483 | for (var columnCounter = 1 ; columnCounter <= colCount; columnCounter++) {
484 | try {
485 |
486 | var f = new File(srcFileList[i]);
487 |
488 | if (f.exists) {
489 |
490 | try {
491 | var prefix = Utils.padNumber(columnCounter, 3) + ' - ';
492 | if (i == 0) {
493 | doc.layers[0].name = prefix + f.name;
494 | }
495 | else {
496 | doc.layers.add().name = prefix + f.name;
497 | }
498 | }
499 | catch(ex) {
500 | Utils.logger(LANG.LAYER_NOT_CREATED + ex);
501 | }
502 |
503 | svgFile = doc.groupItems.createFromFile(f);
504 |
505 | Utils.updateProgress("icons imported");
506 |
507 | var liveWidth = (CONFIG.COLS * (CONFIG.FRM_WIDTH + CONFIG.GUTTER)) - CONFIG.GUTTER;
508 | var hoff = Math.ceil((CONFIG.PG_WIDTH - liveWidth) / 2);
509 |
510 | var myX1 = bounds[0] + hoff + (myColumnWidth * (columnCounter-1));
511 |
512 | var shiftX = Math.ceil((CONFIG.FRM_WIDTH - svgFile.width) / 2);
513 | var shiftY = Math.ceil((CONFIG.FRM_WIDTH - svgFile.height) / 2);
514 |
515 | x1 = myX1 + shiftX;
516 | y1 = (myY1 + shiftY) * -1;
517 |
518 | try {
519 | svgFile.position = [ x1, y1 ];
520 |
521 | if (typeof(svgFile.resize) == "function") {
522 | svgFile.resize(
523 | CONFIG.SCALE,
524 | CONFIG.SCALE,
525 | true,
526 | true,
527 | true,
528 | true,
529 | CONFIG.SCALE
530 | );
531 | }
532 |
533 | redraw();
534 |
535 | /**
536 | * Only save the composite file if at least one
537 | * icon exists and is successfully imported.
538 | * @type {boolean}
539 | */
540 | saveCompositeFile = true;
541 | }
542 | catch(ex) {
543 | Utils.logger(ex);
544 | try { svgFile.position = [0, 0]; }
545 | catch(ex) {/*Exit Gracefully*/}
546 | }
547 | }
548 | else {
549 | Utils.logger(srcFileList[i] + LANG.DOES_NOT_EXIST);
550 | }
551 | }
552 | catch(ex) {
553 | Utils.logger(ex);
554 | }
555 | i++;
556 | }
557 | }
558 | }
559 | }
560 |
561 | Utils.progressBarText("Saving contact sheet");
562 |
563 | if (saveCompositeFile) {
564 | Utils.saveFileAsAi(doc, srcFolder.path + "/" + CONFIG.OUTPUT_FILENAME, CONFIG.AIFORMAT);
565 | }
566 |
567 | Utils.hideProgressBar();
568 | }
569 | }
570 |
571 | doCreateContactSheet();
572 |
573 | userInteractionLevel = originalInteractionLevel;
--------------------------------------------------------------------------------
/Contact Sheet/config.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Global options object used to avoid having to pass a large number of variables in function calls.
3 | * @type {{
4 | * ROWS : int,
5 | * COLS : int,
6 | * VOFF : number,
7 | * HOFF : number,
8 | * ROW_WIDTH : number,
9 | * COL_WIDTH : number,
10 | * FRM_WIDTH : number,
11 | * FRM_HEIGHT : number,
12 | * PG_WIDTH : number,
13 | * PG_HEIGHT : number,
14 | * PG_UNITS : string,
15 | * GUTTER : number,
16 | * SCALE : number,
17 | * AIFORMAT : [*],
18 | * SHRINK_TO_FIT : boolean,
19 | * START_FOLDER : string,
20 | * FILENAME : string,
21 | * LOGGING : boolean,
22 | * LOG_FILE_PATH : string,
23 | * DEBUG : boolean,
24 | * SKIP_COLS : number,
25 | * STRIP : [*]
26 | * }}
27 | */
28 | var CONFIG = {
29 |
30 | /**
31 | * Number of rows
32 | */
33 |
34 | ROWS: 10,
35 |
36 | /**
37 | * Number of columns
38 | */
39 |
40 | COLS: 10,
41 |
42 | /**
43 | * Top & bottom page margins
44 | */
45 |
46 | VOFF: 0,
47 |
48 | /**
49 | * Left & Right page margins
50 | */
51 |
52 | HOFF: 0,
53 |
54 | /**
55 | * Row height. This is set programmatically.
56 | */
57 |
58 | ROW_WIDTH: 64,
59 |
60 | /**
61 | * Column Height. This is set programmatically.
62 | */
63 |
64 | COL_WIDTH: 64,
65 |
66 | /**
67 | * @deprecated
68 | */
69 | FRM_WIDTH: 64,
70 |
71 | /**
72 | * @deprecated
73 | */
74 | FRM_HEIGHT: 64,
75 |
76 | /**
77 | * Artboard width
78 | *
79 | * 10 columns 128 px wide, with 64 px page margins
80 | */
81 |
82 | PG_WIDTH: 1120,
83 |
84 | /**
85 | * Artboard height
86 | *
87 | * 20 rows 128 px tall, with 64 px page margins
88 | */
89 |
90 | PG_HEIGHT: 1400,
91 |
92 | /**
93 | * Page Count
94 | */
95 |
96 | PG_COUNT: 1,
97 |
98 | /**
99 | * Not yet fully-implemented. Will support multiple units
100 | */
101 |
102 | PG_UNITS: "px",
103 |
104 | /**
105 | * @deprecated
106 | */
107 |
108 | GUTTER: 2,
109 |
110 | /**
111 | * Enter scale in percentage 1-100
112 | */
113 |
114 | SCALE: 100,
115 |
116 | /**
117 | * Illustrator version compatibility
118 | */
119 |
120 | AIFORMAT: Compatibility.ILLUSTRATOR10,
121 |
122 | /**
123 | * If the icon is larger than the cell size, shrink it to the cell size
124 | */
125 |
126 | SHRINK_TO_FIT: true,
127 |
128 | /**
129 | * Starting folder for folder selector dialog
130 | */
131 |
132 | START_FOLDER: "~/github/iconify",
133 |
134 | /**
135 | * The contact sheet file name
136 | */
137 |
138 | FILENAME: "contact-sheet",
139 |
140 | /**
141 | * Enable logging?
142 | */
143 |
144 | LOGGING: true,
145 |
146 | /**
147 | * Verbose logging output?
148 | */
149 | DEBUG: true,
150 |
151 | /**
152 | * @deprecated
153 | */
154 |
155 | SKIP_COLS: 0,
156 |
157 | /**
158 | * Not fully-implemented
159 | */
160 |
161 | STRIP: ["svg", "ai", "eps", "txt", "pdf"],
162 |
163 | /**
164 | * Presets folder path
165 | */
166 | PRESETS_FOLDER: '~/ai-contact-sheet/presets',
167 |
168 | /**
169 | * Log folder path
170 | */
171 |
172 | LOG_FOLDER: '~/ai-contact-sheet/logs/',
173 |
174 | /**
175 | * Log file location
176 | */
177 |
178 | LOG_FILE_PATH: '~/ai-contact-sheet/logs/' + Utils.doDateFormat(new Date()) + '-log.txt',
179 |
180 | /**
181 | * Default path separator
182 | */
183 |
184 | PATH_SEPATATOR: "/"
185 | };
--------------------------------------------------------------------------------
/Contact Sheet/lang.jsx:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Global strings object.
4 | * @type {{
5 | * LABEL_DIALOG_WINDOW : string,
6 | * NO_SELECTION : string,
7 | * LABEL_PG_WIDTH : int,
8 | * LABEL_PG_HEIGHT : int,
9 | * LABEL_COL_COUNT : int,
10 | * LABEL_ROW_COUNT : int,
11 | * LABEL_SCALE : number,
12 | * LABEL_FILE_NAME : string,
13 | * LABEL_LOGGING : boolean,
14 | * BUTTON_CANCEL : string,
15 | * BUTTON_OK : string,
16 | * DOES_NOT_EXIST : string,
17 | * LAYER_NOT_CREATED : string,
18 | * LABEL_SRC_FOLDER : string,
19 | * LABEL_CHOOSE_FOLDER : string,
20 | * LABEL_INPUT : string,
21 | * LABEL_SIZE : string,
22 | * LABEL_OUTPUT : string
23 | * }}
24 | */
25 | var LANG = {
26 | /**
27 | * Dialog window label
28 | */
29 | LABEL_DIALOG_WINDOW: "Contact Sheet Settings",
30 |
31 | /**
32 | * Confirm delete preset
33 | */
34 | CONFIRM_DELETE_PRESET: 'Are you sure you want to delete the preset file?',
35 |
36 | /**
37 | * Choose file string
38 | */
39 | CHOOSE_FILE: "Choose a file",
40 |
41 | /**
42 | * No selection error string.
43 | */
44 | NO_SELECTION: "No selection",
45 |
46 | /**
47 | * Page width field label.
48 | */
49 | LABEL_PG_WIDTH: "Page Width:",
50 |
51 | /**
52 | * Page height field label.
53 | */
54 | LABEL_PG_HEIGHT: "Page Height:",
55 |
56 | /**
57 | * Column count field label.
58 | */
59 | LABEL_COL_COUNT: "Column Count:",
60 |
61 | /**
62 | * Row count field label.
63 | */
64 | LABEL_ROW_COUNT: "Row Count:",
65 |
66 | /**
67 | * Scale field label.
68 | */
69 | LABEL_SCALE: "Scale:",
70 |
71 | /**
72 | * File name field label.
73 | */
74 | LABEL_FILE_NAME: "File Name:",
75 |
76 | /**
77 | * Logging field label.
78 | */
79 | LABEL_LOGGING: "Logging?",
80 |
81 | /**
82 | * Cancel button text.
83 | */
84 | BUTTON_CANCEL: "Cancel",
85 |
86 | /**
87 | * OK button text.
88 | */
89 | BUTTON_OK: "Ok",
90 |
91 | /**
92 | * Save button text
93 | */
94 | BUTTON_SAVE: "Save Preset",
95 |
96 | /**
97 | * Delete button text
98 | */
99 | BUTTON_DELETE: "Delete",
100 |
101 | /**
102 | * Object does not exist error string.
103 | */
104 | DOES_NOT_EXIST: " does not exist",
105 |
106 | /**
107 | * Could not create document error string.
108 | */
109 | DOC_NOT_CREATED: "The document could not be created. ",
110 |
111 | /**
112 | * Could not create layer error string.
113 | */
114 | LAYER_NOT_CREATED: "Could not create layer. ",
115 |
116 | /**
117 | * Source folder field label.
118 | */
119 | LABEL_SRC_FOLDER: "Source Folder",
120 |
121 | /**
122 | * Choose folder label.
123 | */
124 | LABEL_CHOOSE_FOLDER: "Choose Folder",
125 |
126 | /**
127 | * Input field label.
128 | */
129 | LABEL_INPUT: "Input",
130 |
131 | /**
132 | * Size field label.
133 | */
134 | LABEL_SIZE: "Size",
135 |
136 | /**
137 | * Output field label.
138 | */
139 | LABEL_OUTPUT: "Output",
140 |
141 | /**
142 | * Presets label
143 | */
144 | LABEL_PRESETS: "Presets"
145 | };
--------------------------------------------------------------------------------
/Contact Sheet/work.js:
--------------------------------------------------------------------------------
1 | for (var i = 0; i < srcFileList.length; i++) {
2 |
3 | // Do some stuff
4 |
5 | for (var pageCounter = 0; pageCounter < CSConfig.PG_COUNT; pageCounter++) {
6 |
7 | // Do some more stuff
8 |
9 | for (var rowCounter = 1 ; rowCounter <= rowCount; rowCounter++) {
10 |
11 | /**
12 | * loop through columns
13 | * @type {Number}
14 | */
15 |
16 | colCount = CSConfig.COLS;
17 |
18 | if (rowCounter > 1) {
19 |
20 | var remaining = Math.ceil(srcFileList.length - i);
21 | if (remaining < colCount) {
22 | colCount = remaining;
23 | }
24 | }
25 |
26 | for (var columnCounter = 1 ; columnCounter <= colCount; columnCounter++) {
27 |
28 | // Do even more stuff
29 |
30 | // We are incrementing the iterator inside the column loop, inside the row loop
31 | // so the outer iterator only increments ever ROWS * COLS iterations.
32 |
33 | i++;
34 | }
35 | }
36 | }
37 | }
38 |
39 | var fileIterator = new Iterator(srcFileList);
40 |
41 | while (fileIterator.hasNext()) {
42 |
43 | // Do some stuff
44 |
45 | for (var pageCounter = 0; pageCounter < CSConfig.PG_COUNT; pageCounter++) {
46 |
47 | // Do some more stuff
48 |
49 | for (var rowCounter = 1 ; rowCounter <= rowCount; rowCounter++) {
50 |
51 | /**
52 | * loop through columns
53 | * @type {Number}
54 | */
55 |
56 | colCount = CSConfig.COLS;
57 |
58 | if (rowCounter > 1) {
59 |
60 | var remaining = Math.ceil(srcFileList.length - i);
61 | if (remaining < colCount) {
62 | colCount = remaining;
63 | }
64 | }
65 |
66 | for (var columnCounter = 1 ; columnCounter <= colCount; columnCounter++) {
67 |
68 | // Do even more stuff
69 |
70 | // We are incrementing the iterator inside the column loop, inside the row loop
71 | // so the outer iterator only increments ever ROWS * COLS iterations.
72 |
73 | f = fileIterator.next();
74 | }
75 | }
76 | }
77 | }
78 |
79 | // VERSION 1
80 |
81 | function doCreateContactSheet() {
82 |
83 | var doc, srcFolder, svgFile, srcFileList, saveCompositeFile;
84 |
85 | saveCompositeFile = false;
86 |
87 | doc = activeDocument;
88 |
89 | var originalInteractionLevel = userInteractionLevel;
90 | userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
91 |
92 | // app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
93 |
94 | if (! doDisplayDialog()) {
95 | return;
96 | }
97 |
98 | if (CSConfig.SRC_FOLDER === null) return;
99 |
100 | srcFolder = CSConfig.SRC_FOLDER;
101 |
102 | srcFileList = new FileList(srcFolder, [FileTypes.SVG]);
103 |
104 | if (srcFileList.length) {
105 |
106 | srcFileList = sortBySetAndName(srcFileList);
107 |
108 | if (Utils.trim(CSConfig.OUTPUT_FILENAME) == "") {
109 | CSConfig.OUTPUT_FILENAME = srcFolder.name.replace(" ", "-") + "-contact-sheet.ai";
110 | }
111 |
112 | CSConfig.PG_COUNT = Math.ceil(srcFileList.length / (CSConfig.ROWS * CSConfig.COLS));
113 |
114 | try {
115 |
116 | Settings = {
117 | colorSpace : DocumentColorSpace.RGB,
118 | layout : DocumentArtboardLayout.GridByCol,
119 | spacing : 32,
120 | columns : Math.round(Math.sqrt(CSConfig.PG_COUNT)),
121 | rowsOrCols : 2
122 | };
123 |
124 | doc = app.documents.add(
125 | Settings.colorSpace,
126 | CSConfig.PG_WIDTH,
127 | CSConfig.PG_HEIGHT,
128 | CSConfig.PG_COUNT,
129 | Settings.layout,
130 | Settings.spacing,
131 | Settings.columns
132 | );
133 | }
134 | catch( ex ) {
135 | logger("Document was not created. " + ex);
136 | return;
137 | }
138 |
139 | var progress = new Progress({
140 | label : 'Create Contact Sheet',
141 | maxvalue : srcFileList.length
142 | }, true);
143 |
144 | var vLayer,
145 | sLayer,
146 | boardName,
147 | setName,
148 | volName;
149 |
150 | var board,
151 | boards,
152 | bounds,
153 | boardWidth,
154 | rowCount,
155 | colCount,
156 | myY1, myY2,
157 | x1, y1, x2, y2,
158 | myRowHeight,
159 | myColumnWidth;
160 |
161 | var ipp = CSConfig.ROWS * CSConfig.COLS;
162 |
163 | for (var i = 0; i < srcFileList.length; i++) {
164 |
165 | x1 = y1 = x2 = y2 = 0;
166 |
167 | myRowHeight = CSConfig.ROW_HEIGHT + CSConfig.GUTTER;
168 | myColumnWidth = CSConfig.COL_WIDTH + CSConfig.GUTTER;
169 |
170 | for (var pageCounter = 0; pageCounter < CSConfig.PG_COUNT; pageCounter++) {
171 |
172 | setName = new File(srcFileList[i]).parent.name;
173 | volName = new File(srcFileList[i]).parent.parent.name;
174 | boardName = volName + '-' + setName + '-' + String(doc.artboards.length-1);
175 |
176 | logger('PageCounter : ' + pageCounter);
177 | logger('i : ' + i);
178 | logger('ipp : ' + ipp);
179 | logger('(i % (ipp - 1)) : ' + (i % (ipp - 1)) );
180 |
181 | boards = doc.artboards;
182 |
183 | boards.setActiveArtboardIndex(pageCounter);
184 | app.executeMenuCommand('fitall');
185 |
186 | logger('Set active artboard to ' + pageCounter);
187 |
188 | // Add Artboard
189 |
190 | board = boards[pageCounter];
191 | board.name = boardName;
192 | bounds = board.artboardRect;
193 | boardWidth = Math.round(bounds[2] - bounds[0]);
194 |
195 | if (Utils.get(vLayer, 'name', null ) != volName) {
196 | vLayer = doc.layers.add();
197 | vLayer.name = volName;
198 | }
199 |
200 | /**
201 | * loop through rows
202 | * @type {number}
203 | */
204 |
205 | rowCount = Math.ceil((srcFileList.length / CSConfig.COLS));
206 | rowCount = CSConfig.ROWS > rowCount ? rowCount : CSConfig.ROWS ;
207 |
208 | for (var rowCounter = 1 ; rowCounter <= rowCount; rowCounter++) {
209 |
210 | myY1 = bounds[1] + CSConfig.MARGIN + (myRowHeight * (rowCounter-1));
211 | myY2 = myY1 + CSConfig.FRM_HEIGHT;
212 |
213 | /**
214 | * loop through columns
215 | * @type {Number}
216 | */
217 |
218 | colCount = CSConfig.COLS;
219 |
220 | if (rowCounter > 1) {
221 |
222 | var remaining = Math.ceil(srcFileList.length - i);
223 | if (remaining < colCount) {
224 | colCount = remaining;
225 | }
226 | }
227 |
228 | for (var columnCounter = 1 ; columnCounter <= colCount; columnCounter++) {
229 | try {
230 |
231 | var f = new File(srcFileList[i]);
232 |
233 | if (f.exists) {
234 |
235 | // Add layers
236 |
237 | // sLayer = getOrAddLayer(f.parent.name, vLayer);
238 | // sLayer.name = f.parent.name;
239 | //
240 | // try {
241 | // sLayer.layers.add().name = f.name.replace(new RegExp(/\s/g), '-');
242 | // }
243 | // catch(ex) {
244 | // logger("Layer " + f.name + " was not created. Error : " + ex);
245 | // }
246 |
247 | svgFile = doc.groupItems.createFromFile(f);
248 |
249 | logger('Item bounds : ' + JSON.stringify(svgFile.geometricBounds));
250 | logger('Artboard bounds : ' + JSON.stringify(bounds));
251 |
252 | progress.update('icons imported');
253 |
254 | // var liveWidth = (CSConfig.COLS * (CSConfig.FRM_WIDTH + CSConfig.GUTTER)) - CSConfig.GUTTER;
255 |
256 | var myX1 = bounds[0] + (myColumnWidth * (columnCounter-1));
257 |
258 | var shiftX = Math.ceil((CSConfig.FRM_WIDTH - svgFile.width) / 2);
259 | var shiftY = Math.ceil((CSConfig.FRM_WIDTH - svgFile.height) / 2);
260 |
261 | x1 = myX1 + shiftX;
262 | y1 = (myY1 + shiftY) * -1;
263 |
264 | try {
265 | svgFile.position = [ x1, y1 ];
266 |
267 | /**
268 | * Only save the composite file if at least one
269 | * icon exists and is successfully imported.
270 | * @type {boolean}
271 | */
272 | saveCompositeFile = true;
273 | }
274 | catch(ex) {
275 | logger(ex);
276 | try { svgFile.position = [0, 0]; }
277 | catch(ex) {/*Exit Gracefully*/}
278 | }
279 |
280 | try {
281 | if (typeof(svgFile.resize) == "function") {
282 | svgFile.resize(
283 | CSConfig.SCALE,
284 | CSConfig.SCALE,
285 | true,
286 | true,
287 | true,
288 | true,
289 | CSConfig.SCALE
290 | );
291 | }
292 | }
293 | catch(e) {
294 | logger(ex);
295 | }
296 |
297 | redraw();
298 | }
299 | else {
300 | logger(srcFileList[i] + " does not exist");
301 | }
302 | }
303 | catch(ex) {
304 | logger(ex);
305 | }
306 | i++;
307 | }
308 | }
309 | }
310 | }
311 |
312 | progress.text('Saving contact sheet');
313 |
314 | if (saveCompositeFile) {
315 | Utils.saveFileAsAi(doc, srcFolder.path + "/" + CSConfig.OUTPUT_FILENAME, CSConfig.AIFORMAT);
316 | }
317 |
318 | progress.close();
319 | }
320 | }
321 |
322 |
323 | // VERSION 2
324 |
325 | function doCreateContactSheet() {
326 |
327 | var doc, srcFolder, svgFile, srcFileList, saveCompositeFile;
328 |
329 | saveCompositeFile = false;
330 |
331 | if (! doDisplayDialog()) {
332 | return;
333 | }
334 |
335 | if (CSConfig.SRC_FOLDER === null) return;
336 |
337 | srcFolder = CSConfig.SRC_FOLDER;
338 |
339 | srcFileList = new FileList(srcFolder, [FileTypes.SVG]);
340 |
341 | if (srcFileList.length) {
342 |
343 | // srcFileList = Utils.sortFileList(srcFileList);
344 |
345 | srcFileList = sortBySetAndName(srcFileList);
346 |
347 | if (Utils.trim(CSConfig.OUTPUT_FILENAME) == "") {
348 | CSConfig.OUTPUT_FILENAME = srcFolder.name.replace(" ", "-") + "-contact-sheet.ai";
349 | }
350 |
351 | CSConfig.PG_COUNT = Math.ceil(srcFileList.length / (CSConfig.ROWS * CSConfig.COLS));
352 |
353 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
354 |
355 | try {
356 |
357 | Settings = {
358 | colorSpace : DocumentColorSpace.RGB,
359 | layout : DocumentArtboardLayout.GridByCol,
360 | spacing : 32,
361 | columns : Math.round(Math.sqrt(CSConfig.PG_COUNT)),
362 | rowsOrCols : 2
363 | };
364 |
365 | doc = app.documents.add(
366 | Settings.colorSpace,
367 | CSConfig.PG_WIDTH,
368 | CSConfig.PG_HEIGHT,
369 | CSConfig.PG_COUNT,
370 | Settings.layout,
371 | Settings.spacing,
372 | Settings.columns
373 | );
374 | }
375 | catch( ex ) {
376 | logger("Document was not created. " + ex);
377 | return;
378 | }
379 |
380 | // try {
381 | // doc = app.documents.add(
382 | // DocumentColorSpace.RGB,
383 | // CSConfig.PG_WIDTH,
384 | // CSConfig.PG_HEIGHT,
385 | // CSConfig.PG_COUNT,
386 | // DocumentArtboardLayout.GridByCol,
387 | // 10,
388 | // Math.round(Math.sqrt(CSConfig.PG_COUNT))
389 | // );
390 | // }
391 | // catch( ex ) {
392 | // logger(LANG.DOC_NOT_CREATED + ex);
393 | // return;
394 | // }
395 |
396 | // Utils.showProgressBar(srcFileList.length);
397 |
398 | var progress = new Progress({
399 | label : 'Create Contact Sheet',
400 | maxvalue : srcFileList.length
401 | }, true);
402 |
403 | var ipp = CSConfig.ROWS * CSConfig.COLS;
404 |
405 | boards = doc.artboards;
406 |
407 | for (var i = 0; i < srcFileList.length; i++) {
408 |
409 | var board,
410 | bounds,
411 | boardWidth,
412 | rowCount,
413 | colCount,
414 | myY1,
415 | myY2,
416 | x1 = y1 = x2 = y2 = 0;
417 |
418 | var myRowHeight = CSConfig.ROW_HEIGHT + CSConfig.GUTTER,
419 | myColumnWidth = CSConfig.COL_WIDTH + CSConfig.GUTTER;
420 |
421 | for (var pageCounter = 0; pageCounter < CSConfig.PG_COUNT; pageCounter++) {
422 |
423 | setName = new File(srcFileList[i]).parent.name;
424 | volName = new File(srcFileList[i]).parent.parent.name;
425 | boardName = volName + '-' + setName + '-' + String(doc.artboards.length-1);
426 |
427 | logger('PageCounter : ' + pageCounter);
428 | logger('i : ' + i);
429 | logger('ipp : ' + ipp);
430 | logger('(i % (ipp - 1)) : ' + (i % (ipp - 1)) );
431 |
432 | var pageID = Utils.padNumber(pageCounter + 1, 3);
433 |
434 | doc.artboards.setActiveArtboardIndex(pageCounter);
435 | app.executeMenuCommand('fitall');
436 |
437 | logger('Set active artboard to ' + pageCounter);
438 |
439 | board = boards[pageCounter];
440 | board.name = boardName;
441 | bounds = board.artboardRect;
442 | boardWidth = Math.round(bounds[2] - bounds[0]);
443 |
444 | // if (Utils.get(vLayer, 'name', null ) != volName) {
445 | // vLayer = doc.layers.add();
446 | // vLayer.name = volName;
447 | // }
448 |
449 | /**
450 | * loop through rows
451 | * @type {number}
452 | */
453 |
454 | rowCount = Math.ceil((srcFileList.length / CSConfig.COLS));
455 | rowCount = CSConfig.ROWS > rowCount ? rowCount : CSConfig.ROWS ;
456 |
457 | for (var rowCounter = 1 ; rowCounter <= rowCount; rowCounter++) {
458 |
459 | myY1 = bounds[1] + CSConfig.MARGIN + (myRowHeight * (rowCounter-1));
460 | myY2 = myY1 + CSConfig.FRM_HEIGHT;
461 |
462 | /**
463 | * loop through columns
464 | * @type {Number}
465 | */
466 |
467 | colCount = CSConfig.COLS;
468 |
469 | if (rowCounter > 1) {
470 |
471 | var remaining = Math.ceil(srcFileList.length - i);
472 | if (remaining < colCount) {
473 | colCount = remaining;
474 | }
475 | }
476 |
477 | for (var columnCounter = 1 ; columnCounter <= colCount; columnCounter++) {
478 | try {
479 |
480 | var f = new File(srcFileList[i]);
481 |
482 | if (f.exists) {
483 |
484 | try {
485 | if (i == 0) {
486 | doc.layers[0].name = pageID + ' - ' + f.name;
487 | }
488 | else {
489 | doc.layers.add().name = pageID + ' - ' + f.name;
490 | }
491 | }
492 | catch(ex) {
493 | logger(LANG.LAYER_NOT_CREATED + ex);
494 | }
495 |
496 | svgFile = doc.groupItems.createFromFile(f);
497 |
498 | // Utils.updateProgress("icons imported");
499 |
500 | progress.update('icons imported');
501 |
502 | var liveWidth = (CSConfig.COLS * (CSConfig.FRM_WIDTH + CSConfig.GUTTER)) - CSConfig.GUTTER;
503 | var hoff = Math.ceil((CSConfig.PG_WIDTH - liveWidth) / 2);
504 |
505 | var myX1 = bounds[0] + hoff + (myColumnWidth * (columnCounter-1));
506 |
507 | var shiftX = Math.ceil((CSConfig.FRM_WIDTH - svgFile.width) / 2);
508 | var shiftY = Math.ceil((CSConfig.FRM_WIDTH - svgFile.height) / 2);
509 |
510 | x1 = myX1 + shiftX;
511 | y1 = (myY1 + shiftY) * -1;
512 |
513 | try {
514 | svgFile.position = [ x1, y1 ];
515 |
516 | if (typeof(svgFile.resize) == "function") {
517 | svgFile.resize(
518 | CSConfig.SCALE,
519 | CSConfig.SCALE,
520 | true,
521 | true,
522 | true,
523 | true,
524 | CSConfig.SCALE
525 | );
526 | }
527 |
528 | redraw();
529 |
530 | /**
531 | * Only save the composite file if at least one
532 | * icon exists and is successfully imported.
533 | * @type {boolean}
534 | */
535 | saveCompositeFile = true;
536 | }
537 | catch(ex) {
538 | logger(ex);
539 | try { svgFile.position = [0, 0]; }
540 | catch(ex) {/*Exit Gracefully*/}
541 | }
542 | }
543 | else {
544 | logger(srcFileList[i] + LANG.DOES_NOT_EXIST);
545 | }
546 | }
547 | catch(ex) {
548 | logger(ex);
549 | }
550 | i++;
551 | }
552 | }
553 | }
554 | }
555 |
556 | // Utils.progressBarText("Saving contact sheet");
557 | progress.text('Saving contact sheet');
558 |
559 | if (saveCompositeFile) {
560 | Utils.saveFileAsAi(doc, srcFolder.path + "/" + CSConfig.OUTPUT_FILENAME, CSConfig.AIFORMAT);
561 | }
562 |
563 | // Utils.hideProgressBar();
564 | progress.close();
565 | }
566 | }
567 |
--------------------------------------------------------------------------------
/Group Overlapping Objects.jsx:
--------------------------------------------------------------------------------
1 | /////////////////////////////////////////////////////////////////
2 | //Group Overlapping (Beta) -- CS, CS2, CS3
3 | //>=--------------------------------------
4 | //
5 | // Groups all overlapping objects in selection into discreet groups.
6 | // The definition for 'overlaping' is based on objects bounding boxes, not their actual geometry.
7 | // Each new groups zOrder is determined by the depth of the front-most object in each group.
8 | // There is no limit to the number of groups created.
9 | // Any non-overlapping objects are ignored.
10 | //
11 | // Note: Currently, this is not very efficient code. It works well on small groups (less than 120 objects)
12 | // and works faster on smaller groupings. Running this on a huge number of objects will likely crash illustrator.
13 | // It serves my purposes, but test it's limits on your machine, and use at your own risk.
14 | // On a 2.53GHz P4, a group of 100 objects took 20 seconds with 2 groups.
15 | //
16 | //
17 | //>=--------------------------------------
18 | // JS code (c) copyright: John Wundes ( john@wundes.com ) www.wundes.com
19 | //copyright full text here: http://www.wundes.com/js4ai/copyright.txt
20 | //////////////////////////////////////////////////////////////////
21 | //this little section is just for testing
22 | //the number of times each function is called.
23 | var testmode = 0;
24 | var t1 = t2 = t3 = t4 = t5 = t6 = t7 = 0;
25 | var testmsg = "";
26 | //
27 | //
28 | //
29 | var go = true;
30 | if (selection.length > 120) {
31 | go = confirm("You have selected " + selection.length + " objects. It is highly recommended that you select less than 120 objects at a time. Do you want to continue anyway?");
32 |
33 | }
34 | if (selection.length > 1 && go == true) {
35 | var groups = 0;
36 | var slen = selection.length;
37 | var hitList = new Array(slen);
38 | var groupArr = new Array(slen);
39 | // for each element in selection
40 | for (var sx = 0; sx < slen; sx++) {
41 | //t6++; //---------------------------------------------loop tracker
42 | var tArr = new Array(0);
43 | // for each element in selection (again)
44 | for (var si = 0; si < slen; si++) {
45 | //t7++; //-------------------------------------loop tracker
46 | groupArr[sx] = tArr;
47 | //note each object hits itself once.
48 | if (hitTest(selection[sx], selection[si])) {
49 | groupArr[sx].push(selection[si]);
50 | }
51 | }
52 | }
53 |
54 | minimize(groupArr);
55 | var zError = 0;
56 | var gaLen = groupArr.length;
57 | for (var each = 0; each < gaLen; each++) {
58 | if (groupArr[each].length > 1) {
59 | groupArr[each].sort(sortBy_zOrder);
60 | }
61 | if (zError == 1) {
62 | alert("cannot read some objects zOrderPosition");
63 | }
64 | //alert("halftime");
65 | for (var each = 0; each < gaLen; each++) {
66 | t1++; //----------------------------------------------loop tracker
67 | if (groupArr[each].length > 1) {
68 | groups++;
69 | groupAll(groupArr[each]);
70 | }
71 | }
72 | //
73 | //---all done with main code, now display statistics if you care...
74 | //
75 | testmsg = "\nObjects processed: " + t1 + "\nObjects grouped: " + t2 + "\nObjects ignored: " + (t1 - t2);
76 |
77 | if (testmode == 1) {
78 | testmsg += "\n\n---testmode data---\nhits compared: " + t5 + "\nfunction 'minimize' called: " + t3 + "\nitems tested within 'minimize': " + t4;
79 | "\nelements: " + t6 + "\nelements*elements: " + t7;
80 | }
81 |
82 | var x = 0;
83 |
84 | while (x < selection.length) {
85 |
86 | if (selection[x].name == "wundes_GO_group") {
87 | selection[x].name = "";
88 | } else {
89 | selection[x].selected = false;
90 | x--;
91 | }
92 | x++;
93 | }
94 | redraw();
95 | alert(groups + " groups created.\n----------------" + testmsg);
96 | }
97 |
98 |
99 | }
100 | //----------------------------------------------------------->
101 | //--------------------------------functions------------------<
102 | //----------------------------------------------------------->
103 |
104 |
105 | function sortBy_zOrder(a, b) {
106 | if (a.zOrderPosition == undefined) {
107 | alert(a.zOrderPosition);
108 | zError = 1;
109 | return 0;
110 | }
111 | var x = Number(a.zOrderPosition);
112 | var y = Number(b.zOrderPosition);
113 |
114 |
115 | return ((x < y) ? -1 : ((x > y) ? 1 : 0));
116 | }
117 |
118 | function groupAll(arr) {
119 | var tempGroup = arr[0].parent.groupItems.add();
120 |
121 | tempGroup.move(arr[0], ElementPlacement.PLACEBEFORE);
122 | var max = arr.length;
123 | for (var i = max - 1; i >= 0; i--) {
124 | t2++; //-----------------------------------------loop tracker
125 | arr[i].move(tempGroup, ElementPlacement.INSIDE);
126 | }
127 | //name the object for selection at end... (will be removed later)
128 | tempGroup.name = "wundes_GO_group";
129 | tempGroup.selected = true;
130 |
131 | }
132 | //---------------hitTest functions ---------------
133 |
134 |
135 | function hitTest(a, b) {
136 | var OK = 0;
137 | if (isWithinX(a, b) || isWithinX(b, a)) {
138 | OK++;
139 | }
140 | if (isWithinY(a, b) || isWithinY(b, a)) {
141 | OK++;
142 | }
143 | if (OK < 2) {
144 | //alert("miss.");
145 | return false;
146 | } else {
147 | //alert("Hit!")
148 | return true;
149 | }
150 | }
151 |
152 | function isWithinX(a, b) {
153 | var p1 = a.geometricBounds[0];
154 | var p2 = b.geometricBounds[0];
155 | if (p2 <= p1 && p1 <= p2 + b.width) {
156 | return true;
157 | } else {
158 | return false;
159 | }
160 | }
161 |
162 | function isWithinY(a, b) {
163 | var p3 = a.geometricBounds[1];
164 | var p4 = b.geometricBounds[1];
165 | if (p3 >= p4 && p4 >= (p3 - a.height)) {
166 | return true;
167 | }
168 | return false;
169 | }
170 |
171 | /*
172 | //-----------------------------------OK, finding groups is done, now do the grouping---------------
173 | */
174 |
175 | function itemize(a) {
176 | var out = "";
177 | return (a.join("\n"));
178 | }
179 |
180 | function minimize(arr) {
181 | for (var e in arr) {
182 | t3++; //-----------------------------------------loop tracker
183 | for (ot in arr) {
184 | t4++; //-------------------------------------loop tracker
185 | if (arr[e] != arr[ot]) {
186 | //if it's not THIS element,
187 | //test for overlaps
188 | if (overlaps(arr[e], arr[ot])) {
189 | merge(arr[e], arr[ot]);
190 | arr[e] = new Array(0);
191 | minimize(arr);
192 | break;
193 | }
194 | }
195 | }
196 | }
197 |
198 | }
199 |
200 | function merge(a, b) {
201 | var alen = a.length;
202 | for (var all = 0; all < alen; all++) {
203 | if (contains(b, a[all])) {
204 | //do nothing
205 | } else {
206 |
207 | b.push(a[all]);
208 |
209 | }
210 | }
211 |
212 | }
213 |
214 | function contains(ar, i) {
215 | for (var all in ar) {
216 | if (ar[all] == i) {
217 | return true;
218 | }
219 | }
220 | return false;
221 | }
222 |
223 |
224 | function overlaps(ar1, ar2) {
225 | for (var each in ar1) {
226 | t5++; //------------------------------------loop tracker
227 | if (contains(ar2, ar1[each])) { //
228 | return true;
229 | }
230 | }
231 | return false;
232 | }
--------------------------------------------------------------------------------
/Helpers.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Astute Graphics
3 | * @copyright 2018 Astute Graphics
4 | * @version 1.0.0
5 | * @url https://astutegraphics.com
6 | * @url https://atomiclotus.net
7 | *
8 | * ABOUT:
9 | *
10 | * Helper functions for general use.
11 | *
12 | * CREDITS:
13 | *
14 | * This extension is based on the CEP Boilerplate extension by Scott Lewis
15 | * at Atomic Lotus, LLC.
16 | *
17 | * NO WARRANTIES:
18 | *
19 | * You are free to use, modify, and distribute this script as you see fit.
20 | * No credit is required but would be greatly appreciated.
21 | *
22 | * THIS SCRIPT IS OFFERED AS-IS WITHOUT ANY WARRANTY OR GUARANTEES OF ANY KIND.
23 | * YOU USE THIS SCRIPT COMPLETELY AT YOUR OWN RISK AND UNDER NO CIRCUMSTANCES WILL
24 | * THE DEVELOPER AND/OR DISTRIBUTOR OF THIS SCRIPT BE HELD LIABLE FOR DAMAGES OF
25 | * ANY KIND INCLUDING LOSS OF DATA OR DAMAGE TO HARDWARE OR SOFTWARE. IF YOU DO
26 | * NOT AGREE TO THESE TERMS, DO NOT USE THIS SCRIPT.
27 | */
28 |
29 | /**
30 | * Test if this class supports the Ai Object type. Before you can use
31 | * this method, define an array in the global scope named `supportedTypes`.
32 | * The underscore indicates the array is meant to be private.
33 | * @param {string} theType
34 | * @returns {boolean}
35 | * @private
36 | */
37 | function isSupported(theType) {
38 | if (typeof(supportedTypes) == 'undefined') {
39 | throw "You must create a global array named `supportedTypes` with the supported type names";
40 | }
41 | return supportedTypes.indexOf(theType.toLowerCase()) >= 0;
42 | }
43 |
44 | /**
45 | * Check the type of an object.
46 | * @param {*} theItem
47 | * @param {string} theType
48 | * @returns {boolean}
49 | * @private
50 | */
51 | function isType(theItem, theType) {
52 | return strcmp(typeof(theItem), theType);
53 | }
54 |
55 | /**
56 | * Check the typename of an AI Object.
57 | * @param {*} theItem
58 | * @param {string} theTypename
59 | * @returns {boolean}
60 | * @private
61 | */
62 | function isTypename(theItem, theTypename) {
63 | if (strcmp(theItem.typename, 'undefined')) return false;
64 | return strcmp(theItem.typename, theTypename);
65 | }
66 |
67 | /**
68 | * Get the typename of an object if it is set.
69 | * @param {object} theItem
70 | * @returns {string|null}
71 | */
72 | function getTypename(theItem) {
73 | if (isDefined(theItem.typename)) return theItem.typename;
74 | return "undefined";
75 | }
76 |
77 | /**
78 | * Is theItem an object?
79 | * @param {*} theItem
80 | * @returns {*}
81 | * @private
82 | */
83 | function isObject(theItem) {
84 | return isType(theItem, 'object');
85 | }
86 |
87 | /**
88 | * Is theItem a function?
89 | * @param {*} theItem
90 | * @returns {boolean}
91 | * @private
92 | */
93 | function isFunction(theItem) {
94 | return isType(theItem, 'function');
95 | }
96 |
97 | /**
98 | * Is theItem a string?
99 | * @param {*} theItem
100 | * @returns {boolean}
101 | */
102 | function isString(theItem) {
103 | return isType(theItem, 'string');
104 | }
105 |
106 | /**
107 | * Is theItem a number?
108 | * @param {*} theItem
109 | * @returns {boolean}
110 | */
111 | function isNumber(theItem) {
112 | return ! isNaN(theItem);
113 | }
114 |
115 | /**
116 | * Determine if a value is true-ish.
117 | * USE ONLY with strings, ints, and booleans.
118 | * @param what
119 | * @returns {boolean}
120 | */
121 | function isTrue(what) {
122 |
123 | if (isTrue === true) return true;
124 |
125 | if (isString(what)) {
126 | var truish = [
127 | 'yes', 'oui', 'ja', 'da',
128 | 'si', 'yeah', 'yep', 'yup',
129 | 'fuck yes', 'fuck yeah', 'fuckin a',
130 | 'you know it', 'of course'
131 | ];
132 | what = what.toLowerCase();
133 | if (what === "true") return true;
134 | if (truish.indexOf(what) != -1) return true;
135 | }
136 |
137 | if (! isNaN(what)) {
138 | if (parseInt(what) > 0) return true;
139 | }
140 |
141 | return false;
142 | }
143 |
144 | /**
145 | * Is theString an error (Starts with the word 'Error')?
146 | * @param {string} theString
147 | * @returns {boolean}
148 | */
149 | function isErrorString(theString) {
150 | return theString.substr(0, 5).toLowerCase() == 'error';
151 | }
152 |
153 | /**
154 | * Is theItem a GroupItem?
155 | * @param {*} theItem
156 | * @returns {boolean}
157 | * @private
158 | */
159 | function isGroupItem(theItem) {
160 | return isTypename(theItem, 'GroupItem');
161 | }
162 |
163 | /**
164 | * Is theItem a PathItem?
165 | * @param {*} theItem
166 | * @returns {boolean}
167 | * @private
168 | */
169 | function isPathItem(theItem) {
170 | return isTypename(theItem, 'PathItem');
171 | }
172 |
173 | /**
174 | * Is theItem a CompoundPathItem?
175 | * @param {GroupItem} theItem
176 | * @returns {boolean}
177 | * @private
178 | */
179 | function isCompoundPathItem(theItem) {
180 | return isTypename(theItem, 'CompoundPathItem');
181 | }
182 |
183 | /**
184 | * Test if a value is defined.
185 | * @param {string} property
186 | * @returns {boolean}
187 | * @private
188 | */
189 | function isDefined(theItem) {
190 | return typeof(theItem) != 'undefined';
191 | }
192 |
193 | /**
194 | * If theItem is defined, return it, otherwise set it to theDefault value.
195 | * @param {*} theItem
196 | * @param {*) theDefault
197 | * @returns {boolean|*}
198 | */
199 | function isDefinedOr(theItem, theDefault) {
200 | if (typeof(theItem) != 'undefined') {
201 | return theItem;
202 | }
203 | return theDefault;
204 | }
205 |
206 | /**
207 | * If theItem is not empty, return it, otherwise set it to theDefault value.
208 | * @param {*} theItem
209 | * @param {*) theDefault
210 | * @returns {boolean|*}
211 | */
212 | function isEmptyOr(theItem, theDefault) {
213 | if (! isEmpty(theItem)) {
214 | return theItem;
215 | }
216 | return theDefault;
217 | }
218 |
219 | /**
220 | * Get the current timestamp.
221 | * @returns {number}
222 | * @private
223 | */
224 | function now() {
225 | return (new Date()).getTime();
226 | }
227 |
228 | /**
229 | * Ensures a URL ends with a trailing slash.
230 | * @param url
231 | * @returns {*}
232 | */
233 | function slash(url) {
234 | if (url.charAt(url.length-1) != '/') {
235 | url += '/';
236 | }
237 | return url;
238 | };
239 |
240 | /**
241 | * Appends a string to a base string using a divider.
242 | * @param {string} base
243 | * @param {string} add
244 | * @param {string} divider
245 | * @returns {string}
246 | */
247 | function concat(base, add, divider) {
248 | if (base.charAt(base.length-1) != divider) {
249 | base += divider;
250 | }
251 | return base + add;
252 | }
253 |
254 | /**
255 | * Case-insensitive string comparison.
256 | * @param {string} aText
257 | * @param {string} bText
258 | * @returns {boolean}
259 | */
260 | function strcmp(aText, bText) {
261 | return aText.toLowerCase() == bText.toLowerCase();
262 | }
263 |
264 | /**
265 | * Trap function execution in a try/catch block.
266 | * @param {function} func
267 | * @returns {*}
268 | */
269 | function trap(func, customError) {
270 | try {
271 | return func();
272 | }
273 | catch(e) {
274 | return customError || e.message ;
275 | }
276 | }
277 |
278 | /**
279 | * Test of a variable is completely empty.
280 | * @param {*} data
281 | * @returns {boolean}
282 | */
283 | function isEmpty(data) {
284 | if (typeof(data) == 'number' || typeof(data) == 'boolean') {
285 | return false;
286 | }
287 | if (typeof(data) == 'undefined' || data === null) {
288 | return true;
289 | }
290 | if (typeof(data.length) != 'undefined') {
291 | return data.length == 0;
292 | }
293 | var count = 0;
294 | for (var i in data) {
295 | if (data.hasOwnProperty(i)) count ++;
296 | }
297 | return count == 0;
298 | }
299 |
300 | /**
301 | * Convert XML document to string.
302 | * @param {XmlDocument} xmlData
303 | * @returns {string}
304 | */
305 | function xmlToString(xmlData) {
306 | //IE
307 | if (window.ActiveXObject){
308 | return xmlData.xml;
309 | }
310 | // Everyone else.
311 | return (new XMLSerializer()).serializeToString(xmlData);
312 | }
313 |
314 | /**
315 | * Trim newline chars from a long string.
316 | * @param {string} theText
317 | * @returns {string}
318 | */
319 | function trimNewLines(theText) {
320 | return theText.replace(/\r?\n/g, "");
321 | }
322 |
323 | /**
324 | * Remove empty group nodes from SVG.
325 | * @param {XmlDocument} $svg
326 | * @returns {XmlDocument}
327 | */
328 | function removeEmptyNodes($svg) {
329 | $("g", $svg).each(function(i) {
330 | var $group = $(this);
331 | if ($.trim($group.text()) == "") {
332 | $group.remove();
333 | }
334 | });
335 | return $svg;
336 | }
337 |
338 | /**
339 | * Set the PathPoints in an AI PathItem from SVG path value.
340 | * @param {PathItem} path
341 | * @param {string} svg
342 | *
343 | * @author Malcolm McLean
344 | */
345 | function setPathItemFromSVG(path, svg)
346 | {
347 | var i;
348 | var pp;
349 | var pointArray = svgToPathPointArray(svg);
350 |
351 | while(path.pathPoints.length > 1)
352 | {
353 | path.pathPoints[0].remove();
354 | }
355 | path.pathPoints[0].anchor = pointArray[0].anchor;
356 | path.pathPoints[0].leftDirection = pointArray[0].leftDirection;
357 | path.pathPoints[0].rightDirection = pointArray[0].rightDirection;
358 |
359 | for(i=1;i 1) {
386 | targetPath[targetPPKey][0].remove();
387 | }
388 |
389 | pointArray = sourcePath[sourcePPKey];
390 |
391 | targetPath[targetPPKey][0].anchor = pointArray[0].anchor;
392 | targetPath[targetPPKey][0].leftDirection = pointArray[0].leftDirection;
393 | targetPath[targetPPKey][0].rightDirection = pointArray[0].rightDirection;
394 |
395 | for(i=1; i < pointArray.length; i++) {
396 | try {
397 | pp = targetPath[targetPPKey].add();
398 | pp.anchor = pointArray[i].anchor;
399 | pp.leftDirection = pointArray[i].leftDirection;
400 | pp.rightDirection = pointArray[i].rightDirection;
401 | pp.pointType = PointType.CORNER;
402 | }
403 | catch(e) {
404 | Utils.dump("[copyPathPoints()#targetPath[targetPPKey].add()] " + e.message);
405 | }
406 | }
407 | }
408 |
409 | /**
410 | * Converts SVG Path value to cubic bezier points.
411 | * @param {string} svg
412 | * @returns {Array}
413 | *
414 | * @author Malcolm McLean
415 | */
416 | function svgToPathPointArray(svg)
417 | {
418 | var result = [];
419 | var splits = svg.split("C");
420 | var i;
421 | var point = {};
422 | var start = splits[0].slice(1, splits[0].length);
423 | var starts = start.split(",");
424 | if(starts.length != 2)
425 | {
426 | return [];
427 | }
428 | point.anchor = [parseFloat(starts[0]), parseFloat(starts[1])];
429 | result.push(point);
430 | point = {};
431 | for(i=1; i < splits.length;i++)
432 | {
433 | point = {};
434 | segs = splits[i].split(",");
435 | if(segs.length != 6)
436 | {
437 | return [];
438 | }
439 | result[i-1].rightDirection = [parseFloat(segs[0]), parseFloat(segs[1])];
440 | point.leftDirection = [parseFloat(segs[2]), parseFloat(segs[3])];
441 | point.anchor = [parseFloat(segs[4]), parseFloat(segs[5])];
442 | result.push(point);
443 | }
444 | if(svg.indexOf("Z"))
445 | {
446 | result[0].leftDirection = point.leftDirection;
447 | point = {};
448 | if(result.length > 1)
449 | {
450 | result.pop();
451 | }
452 | }
453 | for(i=0;i
472 | */
473 | function pathItemToSVG(path)
474 | {
475 | var i;
476 | var answer = "";
477 | var ppa;
478 | var ppb;
479 |
480 | if(path.pathPoints.length == 0)
481 | return "";
482 |
483 |
484 | answer = "M" + path.pathPoints[0].anchor[0].toFixed(2) + "," + path.pathPoints[0].anchor[1].toFixed(2);
485 |
486 |
487 | for(i=0;i this.items.length) return false;
323 | }
324 |
325 | /**
326 | * Gets the size of the iterable collection.
327 | * @returns {Number}
328 | */
329 | Iterator.prototype.size = function() {
330 | return this.items.length;
331 | }
332 |
--------------------------------------------------------------------------------
/JSON.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Add Array.indexOf support if not supported natively.
3 | */
4 | if(!Array.prototype.indexOf) {
5 | /**
6 | * Gets the index of an element in an array.
7 | * @param what
8 | * @param i
9 | * @returns {*}
10 | */
11 | Array.prototype.indexOf = function(what, i) {
12 | i = i || 0;
13 | var L = this.length;
14 | while (i < L) {
15 | if(this[i] === what) return i;
16 | ++i;
17 | }
18 | return -1;
19 | };
20 | }
21 |
22 | /**
23 | * Add Array.remove support.
24 | * @returns {Array}
25 | */
26 | Array.prototype.remove = function() {
27 | var what, a = arguments, L = a.length, ax;
28 | while (L && this.length) {
29 | what = a[--L];
30 | while ((ax = this.indexOf(what)) !== -1) {
31 | this.splice(ax, 1);
32 | }
33 | }
34 | return this;
35 | };
36 |
37 | /*-------------------------------------------------------------------------------------------------------------------------*/
38 | /**
39 | * Adds JSON library support for engines that do not include it natively.
40 | */
41 | "object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(t){return 10>t?"0"+t:t}function quote(t){
42 | return escapable.lastIndex=0,escapable.test(t)?'"'+t.replace(escapable,function(t){var e=meta[t];
43 | return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}
44 | function str(t,e){var n,r,o,f,u,i=gap,p=e[t];switch(p&&"object"==typeof p&&"function"==typeof p.toJSON&&(p=p.toJSON(t)),
45 | "function"==typeof rep&&(p=rep.call(e,t,p)),typeof p){case"string":return quote(p);case"number":return isFinite(p)?String(p):"null";
46 | case"boolean":case"null":return String(p);case"object":if(!p)return"null";if(gap+=indent,u=[],"[object Array]"===Object.prototype.toString.apply(p)){
47 | for(f=p.length,n=0;f>n;n+=1)u[n]=str(n,p)||"null";return o=0===u.length?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+i+"]":"["+u.join(",")+"]",gap=i,o}
48 | if(rep&&"object"==typeof rep)for(f=rep.length,n=0;f>n;n+=1)"string"==typeof rep[n]&&(r=rep[n],o=str(r,p),o&&u.push(quote(r)+(gap?": ":":")+o));
49 | else for(r in p)Object.prototype.hasOwnProperty.call(p,r)&&(o=str(r,p),o&&u.push(quote(r)+(gap?": ":":")+o));return o=0===u.length?"{}":gap?"{\n"+gap+
50 | u.join(",\n"+gap)+"\n"+i+"}":"{"+u.join(",")+"}",gap=i,o}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){
51 | return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+
52 | f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){
53 | return this.valueOf()});var cx,escapable,gap,indent,meta,rep;"function"!=typeof JSON.stringify&&
54 | (escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
55 | meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(t,e,n){var r;
56 | if(gap="",indent="","number"==typeof n)for(r=0;n>r;r+=1)indent+=" ";else"string"==typeof n&&(indent=n);if(rep=e,
57 | e&&"function"!=typeof e&&("object"!=typeof e||"number"!=typeof e.length))throw new Error("JSON.stringify");return str("",{"":t})}),
58 | "function"!=typeof JSON.parse&&(cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
59 | JSON.parse=function(text,reviver){function walk(t,e){var n,r,o=t[e];if(o&&"object"==typeof o)for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&
60 | (r=walk(o,n),void 0!==r?o[n]=r:delete o[n]);return reviver.call(t,e,o)}var j;if(text=String(text),cx.lastIndex=0,cx.test(text)&&
61 | (text=text.replace(cx,function(t){return"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})),
62 | /^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@")
63 | .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]")
64 | .replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;
65 | throw new SyntaxError("JSON.parse")})}();
66 | /*-------------------------------------------------------------------------------------------------------------------------*/
67 |
--------------------------------------------------------------------------------
/Merge SVG Docs.jsx:
--------------------------------------------------------------------------------
1 | #target illustrator
2 | #include "~/github/iconify/merge-svg-docs/Merge SVG Docs.jsx";
--------------------------------------------------------------------------------
/Progress.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 Scott Lewis
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | */
25 |
26 | var Progress = {
27 |
28 | top: 0,
29 |
30 | left: 0,
31 |
32 | width: 450,
33 |
34 | height: 100,
35 |
36 | minvalue: 0,
37 |
38 | maxvalue: 100,
39 |
40 | window: null,
41 |
42 | panel: null,
43 |
44 | init: function(start, end) {
45 |
46 | Progress.minvalue = start;
47 | Progress.maxvalue = end;
48 |
49 | var top, right, bottom, left;
50 |
51 | Progress.top = 0;
52 | Progress.left = 0;
53 | Progress.width = 450;
54 | Progress.height = 100;
55 |
56 | if ( bounds = Utils.getScreenSize() ) {
57 | left = Math.abs(Math.ceil((bounds.width/2) - (Progress.width/2)));
58 | top = Math.abs(Math.ceil((bounds.height/2) - (Progress.height/2)));
59 | }
60 |
61 | Progress.window = new Window(
62 | 'palette',
63 | 'Progress',
64 | [left, top, left + Progress.width, top + Progress.height]
65 | );
66 |
67 | Progress.window.pnl = progress.add(
68 | 'panel',
69 | [10, 10, 440, 100],
70 | 'Progress'
71 | );
72 |
73 | Progress.window.pnl.progBar = progress.pnl.add(
74 | 'progressbar',
75 | [20, 35, 410, 60],
76 | 0,
77 | Progress.maxvalue
78 | );
79 |
80 | Progress.window.pnl.progBarLabel = progress.pnl.add(
81 | 'statictext',
82 | [20, 20, 320, 35],
83 | "0 of " + Progress.maxvalue
84 | );
85 | },
86 |
87 | show: function() {
88 | try { Progress.close(); } catch(e){};
89 | Progress.obj.show();
90 | },
91 |
92 | update: function() {
93 | Progress.window.pnl.progBar.value++;
94 | var val = Progress.window.pnl.progBar.value;
95 | var max = Progress.window.pnl.progBar.maxvalue;
96 | Progress.window.pnl.progBarLabel.text = val + ' of ' + max;
97 | $.sleep(10);
98 | Progress.window.update();
99 | },
100 |
101 | close: function() {
102 | Progress.window.close();
103 | }
104 | };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ai Scripts
2 |
3 | My collection of Ai JSX scripts I use day-to-day
4 |
5 | ## Installation
6 |
7 | Copy the contents of this folder to `Adobe Illustrator/Presets/EN_US/Scripting/`
8 |
9 | Replace `EN_US` with whatever language you are using.
10 |
11 | ## Ai Sessions
12 |
13 | This script will save a list of currently open documents to a small JSON file in your home directory. You can re-open the same collection of files any time by running the script and choesing the Session date from the list. Only the 10 most recent sessions are saved.
14 |
15 | ### Usage:
16 |
17 | 1. Navigate to `File / Scripts / Ai Sessions`
18 | 2. Click `Save` to save the current session
19 | 3. To return to a session navigate to `File / Scripts / Ai Sessions`
20 | 4. Select the desired session date from the list
21 |
22 | ## Batch Resize Artboards
23 |
24 | This script will resize all artboards in all documents in a folder (such as a folder of SVG files).
25 |
26 | ### Usage
27 |
28 | 1. Navigate to `File / Scripts / Batch Resize Artboards`
29 | 2. When prompted, select the desired folder of files to resize
30 | 3. When prompted, enter an integer value for the width/height of the new artboards.
31 |
32 |
33 | ## Contact Sheet
34 |
35 | This script creates a contact sheet from a source folder of SVG files. For more details see https://github.com/iconfinder/scripts-for-icondesigners/tree/master/icon-contact-sheet
36 |
37 | ## Merge SVG Docs
38 |
39 | This script will merge a folder of SVG files into a single document. Each SVG file will be placed on its own artboard. The artboard name will match the file name minus the file extension.
40 |
41 | Since Illustrator is currently limited to 100 artboards per file, the script can only accommodate 100 files max. If you have more than 100 files, split them into multiple folders.
42 |
43 | ### Usage
44 |
45 | 1. Navigate to `File / Scripts / Merge SVG Docs`
46 | 2. When prompted, select the desired folder of files to merge
47 |
48 | ## MoveItemsToNearestPixel
49 |
50 | This script will move all items in an illustrator file to the nearest pixel.
51 |
52 | ### Usage
53 |
54 | 1. With an open Illustrator document
55 | 2. Navigate to `File / Scripts / MoveItemsToNearestPixel`
56 |
57 | ## MultiExporter
58 |
59 | Exports all groups or layers in an Illustrator document to individual SVG or PDF files.
60 |
61 | This script is a modified version of the script by the same name by Matthew Ericson - mericson@ericson.net
62 |
63 | _Copyright 2011 Matthew Ericson_
64 | _Comments or suggestions to mericson@ericson.net_
65 |
66 | ## ResizeAllArtboards
67 |
68 | This script resizes all artboards in an open Ai document.
69 |
70 | ### Usage
71 |
72 | 1. Navigate to `File / Scripts / Resize All Artboards`
73 | 2. When prompted, enter an integer value for the width/height of the new artboards.
74 |
75 | ## Smart Layer Export
76 |
77 | This script exports any layers, Groups, or artboards whose name ends with `.svg` as an SVG file.
78 |
79 | This script is a modified version of the script by the same name by P. J. Onori as part of the Iconic system.
80 | For more information, please visit
81 |
82 | ## z_Adobe
83 |
84 | This is an archive folder of the default Adobe Illustrator scripts.
85 |
86 | ## z_Iconify
87 |
88 | This is an archive folder of older versions of scripts I use.
--------------------------------------------------------------------------------
/Resize All Artboards.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Based on the script resizeArtboards_CS4andUp.jsx by Carlos Canto 11/4/12
3 | */
4 |
5 | #target Illustrator
6 |
7 | var OPTIONS = {
8 | size : 32,
9 | width : 32,
10 | height : 32
11 | };
12 |
13 | if (app.documents.length == 0) {
14 | alert("there are no open documents");
15 | }
16 | else {
17 | var idoc = app.activeDocument;
18 | var title = "Resize All Artboards";
19 |
20 | OPTIONS.size = Window.prompt ("Enter New Artboard size in pixels as WxH ( Example: 250x300 )", 32, title);
21 |
22 | if (OPTIONS.size.indexOf('x') != -1) {
23 | var bits = OPTIONS.size.split('x');
24 | OPTIONS.width = parseInt(bits[0]);
25 | OPTIONS.height = parseInt(bits[1]);
26 | }
27 | else {
28 | OPTIONS.width = OPTIONS.size;
29 | OPTIONS.height = OPTIONS.size;
30 | }
31 |
32 | try {
33 | var width = OPTIONS.width;
34 | var height = OPTIONS.height;
35 |
36 | for (i=0; i 0 ) {
88 |
89 | svgOptions = new SVGExportOptions();
90 | itemsToExport = [];
91 | sourceDoc = app.activeDocument;
92 | exportFolder = Folder.selectDialog('Select Folder to Save Files');
93 | // exportDoc = documents.add( DocumentColorSpace.RGB );
94 |
95 | main();
96 |
97 | // exportDoc.close(SaveOptions.DONOTSAVECHANGES);
98 | }
99 | else{
100 | error(new Error('There are no documents open. Open a document and try again.'));
101 | throw new Error('There are no documents open. Open a document and try again.');
102 | }
103 | }
104 | catch(e) {
105 | error(e.message);
106 | alert(e.message, "Script Alert", true);
107 | }
108 |
109 | function main() {
110 |
111 | var idx,
112 | item;
113 |
114 | try {
115 | info('Set activeDocument to sourceDoc');
116 |
117 | app.activeDocument = sourceDoc;
118 |
119 | info('Mark random artbaords for export');
120 |
121 | getRandomNamedItems(sourceDoc, 100);
122 |
123 | info('Get indices of exportable artboards');
124 |
125 | itemsToExport = getNamedArtboardsByIndex(sourceDoc);
126 |
127 | info('Indices : ' + itemsToExport);
128 | info('Show progress bar');
129 |
130 | Utils.showProgressBar(itemsToExport.length);
131 |
132 | for ( var i = 0; i < itemsToExport.length; i++ ) {
133 |
134 | try {
135 |
136 | info('Set activeDocument to sourceDoc');
137 |
138 | app.activeDocument = sourceDoc;
139 |
140 | idx = itemsToExport[i];
141 |
142 | info('Set active artboard to ' + idx);
143 |
144 | sourceDoc.artboards.setActiveArtboardIndex(idx);
145 |
146 | item = sourceDoc.artboards[sourceDoc.artboards.getActiveArtboardIndex()];
147 |
148 | info('Update progress bar');
149 | info("Exporting item " + item.name);
150 |
151 | Utils.updateProgressMessage( "Exporting item " + item.name );
152 |
153 | exportArtboard(item);
154 |
155 | // redraw();
156 | }
157 | catch(e) { error(e) }
158 |
159 | Utils.updateProgress( item.name + " was exported" );
160 | }
161 |
162 | resetArtboardNames();
163 | }
164 | catch(e) { error(e) }
165 |
166 | Utils.progress.close();
167 |
168 | }
169 |
170 | function exportArtboard(artboard) {
171 |
172 | var name,
173 | aBounds,
174 | gBounds,
175 | aWidth,
176 | aHeight,
177 | gWidth,
178 | gHeight,
179 | gPosition,
180 | pastedItem,
181 | theGroupItem;
182 |
183 | app.activeDocument = sourceDoc;
184 |
185 | name = artboard.name;
186 |
187 | info('name : ' + name);
188 | info('Clear previous selections');
189 |
190 | sourceDoc.selection = null;
191 |
192 | info('Select items on artboard ' + name);
193 |
194 | sourceDoc.selectObjectsOnActiveArtboard();
195 |
196 | info('Group selection');
197 | info('Selection length : ' + sourceDoc.selection.length);
198 |
199 | app.executeMenuCommand('group');
200 |
201 | info('Get selection');
202 |
203 | theGroupItem = sourceDoc.selection[0];
204 |
205 | aBounds = artboard.artboardRect;
206 | gBounds = theGroupItem.geometricBounds;
207 | gWidth = theGroupItem.width;
208 | gHeight = theGroupItem.height;
209 | gPosition = theGroupItem.position;
210 | aWidth = aBounds[2] - aBounds[2];
211 | aHeight = aBounds[1] - aBounds[3];
212 |
213 | info('aBounds : ' + aBounds);
214 | info('gBounds : ' + gBounds);
215 | info('Copy the Group Item');
216 |
217 | app.executeMenuCommand('copy');
218 |
219 | info('Add export document');
220 |
221 | exportDoc = app.documents.add(DocumentColorSpace.RGB);
222 |
223 | info('Set active document to exportDoc');
224 |
225 | app.activeDocument = exportDoc;
226 |
227 | info('fit to window');
228 |
229 | app.executeMenuCommand('fitall');
230 |
231 | info('app.coordinateSystem is ' + app.coordinateSystem);
232 | info('Set app.coordinateSystem to ' + CoordinateSystem.ARTBOARDCOORDINATESYSTEM );
233 |
234 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
235 |
236 | info('pasteFront in exportDoc');
237 |
238 | try {
239 | info('Delete items in exportDoc before pasting new image');
240 | exportDoc.selectObjectsOnActiveArtboard();
241 | exportDoc.selection[0].remove();
242 | }
243 | catch(e) {
244 | info('No items to delete before pasting');
245 | }
246 |
247 | app.executeMenuCommand('paste');
248 |
249 | info('Tested successfully to this point');
250 | info('Selected copied item');
251 |
252 | exportDoc.selectObjectsOnActiveArtboard();
253 |
254 | info('Get selection');
255 |
256 | pastedItem = exportDoc.selection[0];
257 |
258 | info('Set pasted item position to ' + gPosition);
259 |
260 | pastedItem.position = gPosition;
261 |
262 | if (! exportDoc.pageItems.length) return;
263 |
264 | info('Set exportDoc layer name');
265 |
266 | exportDoc.layers[0].name = name;
267 |
268 | info('Attempt to export SVG');
269 |
270 | exportSVG( exportDoc, name, aBounds, svgOptions );
271 | }
272 |
273 | function exportSVG(doc, name, bounds, exportOptions) {
274 |
275 | doc.artboards[0].artboardRect = bounds;
276 |
277 | doc.exportFile(
278 | new File( exportFolder.fsName + '/' + name ),
279 | ExportType.SVG,
280 | exportOptions
281 | );
282 |
283 | doc.close(SaveOptions.DONOTSAVECHANGES);
284 | }
285 |
286 | function resize(target, scale) {
287 | if (typeof(target.resize) == "function") {
288 | target.resize(
289 | scale,
290 | scale,
291 | true,
292 | true,
293 | true,
294 | true,
295 | scale
296 | );
297 | }
298 | else {
299 |
300 | }
301 | }
302 |
303 |
304 | function centerOnArtboard() {
305 |
306 | var doc = app.activeDocument;
307 | var count = doc.artboards.length;
308 | var __SCALE = 22.222;
309 |
310 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
311 |
312 | for (var i = 0; i < count; i++) {
313 | doc.artboards.setActiveArtboardIndex(i);
314 | // doc.selection = null;
315 |
316 | var board = doc.artboards[doc.artboards.getActiveArtboardIndex()];
317 | var right = board.artboardRect[2];
318 | var bottom = board.artboardRect[3];
319 |
320 | doc.selectObjectsOnActiveArtboard();
321 |
322 | app.executeMenuCommand('group');
323 |
324 | for (var x = 0 ; x < doc.selection.length; x++) {
325 | try {
326 | doc.selection[x].position = [
327 | Math.round((right - doc.selection[x].width)/2),
328 | Math.round((bottom + doc.selection[x].height)/2)
329 | ];
330 |
331 | // resize(doc.selection[x], __SCALE);
332 |
333 | resizeArtboard();
334 |
335 | }
336 | catch(e) {
337 | alert(e);
338 | }
339 | }
340 | }
341 |
342 | redraw();
343 | }
344 |
345 | function resizeArtboard() {
346 |
347 | var OPTIONS = {
348 | size : 32,
349 | width : 32,
350 | height : 32
351 | };
352 |
353 | if (app.documents.length > 0) {
354 |
355 | var idoc = app.activeDocument;
356 | var title = "Resize All Artboards";
357 |
358 | OPTIONS.size = "64x64";
359 |
360 | if (OPTIONS.size.indexOf('x') != -1) {
361 | var bits = OPTIONS.size.split('x');
362 | OPTIONS.width = parseInt(bits[0]);
363 | OPTIONS.height = parseInt(bits[1]);
364 | }
365 | else {
366 | OPTIONS.width = OPTIONS.size;
367 | OPTIONS.height = OPTIONS.size;
368 | }
369 |
370 | try {
371 | var width = OPTIONS.width;
372 | var height = OPTIONS.height;
373 |
374 | for (i=0; i 0) {
536 | recurseLayers( layer.layers, layerArray );
537 | }
538 | }
539 | }
540 |
541 | function recurseItems(layers, items) {
542 |
543 | var layer;
544 |
545 | for ( var i = 0, len = layers.length; i < len; i++ ) {
546 | layer = layers[i];
547 | if ( layer.pageItems.length > 0 && !layer.locked ) {
548 | for ( var j = 0, plen = layer.pageItems.length; j < plen; j++ ) {
549 | if ( !layer.pageItems[j].locked ) {
550 | items.push(layer.pageItems[j]);
551 | }
552 | }
553 | }
554 |
555 | if ( layer.layers.length > 0 ) {
556 | recurseItems( layer.layers, items );
557 | }
558 | }
559 | }
560 |
561 | function anyParentLocked(item) {
562 | while ( item.parent ) {
563 | if ( item.parent.locked ) {
564 | return true;
565 | }
566 | item = item.parent;
567 | }
568 |
569 | return false;
570 | }
571 |
572 |
573 | /* Code derived from John Wundes ( john@wundes.com ) www.wundes.com
574 | * Copyright (c) 2005 wundes.com
575 | * All rights reserved.
576 | *
577 | * This code is derived from software contributed to or originating on wundes.com
578 | */
579 |
580 | function hitTest(a,b){
581 | if (!hitTestX(a,b)){
582 | return false;
583 | }
584 | if (!hitTestY(a,b)){
585 | return false;
586 | }
587 | return true;
588 | }
589 |
590 | function hitTestX(a,b){
591 | var p1 = a.visibleBounds[0];
592 | var p2 = b.visibleBounds[0];
593 | if ( (p2<=p1 && p1<=p2+b.width) || (p1<=p2 && p2<=p1+a.width) ) {
594 | return true;
595 | }
596 | return false;
597 | }
598 |
599 | function hitTestY(a,b){
600 | var p3 = a.visibleBounds[1];
601 | var p4 = b.visibleBounds[1];
602 | if ( (p3>=p4 && p4>=(p3-a.height)) || (p4>=p3 && p3>=(p4-b.height)) ) {
603 | return true;
604 | }
605 | return false;
606 | }
607 |
--------------------------------------------------------------------------------
/Save Open Docs.jsx:
--------------------------------------------------------------------------------
1 | /**
* @author Scott Lewis
* @copyright 2017 Scott Lewis
* @version 1.0.0
* @url http://github.com/iconifyit
*
* ABOUT:
*
* This script demonstrates how to implement a progress bar in your script.
*
* USAGE:
*
* 1. Place this script in Applications > Adobe Illustrator > Presets > en_US > Scripts
* 2. Restart Adobe Illustrator to activate the script
* 3. The script will be available under menu File > Scripts > Ai Sessions
*
* NO WARRANTIES:
*
* You are free to use, modify, and distribute this script as you see fit.
* No credit is required but would be greatly appreciated.
*
* THIS SCRIPT IS OFFERED AS-IS WITHOUT ANY WARRANTY OR GUARANTEES OF ANY KIND.
* YOU USE THIS SCRIPT COMPLETELY AT YOUR OWN RISK AND UNDER NO CIRCUMSTANCES WILL
* THE DEVELOPER AND/OR DISTRIBUTOR OF THIS SCRIPT BE HELD LIABLE FOR DAMAGES OF
* ANY KIND INCLUDING LOSS OF DATA OR DAMAGE TO HARDWARE OR SOFTWARE. IF YOU DO
* NOT AGREE TO THESE TERMS, DO NOT USE THIS SCRIPT.
*/
/**
* Declare the target app.
*/
#target illustrator
/**
* Include the libraries we need.
*/
#includepath "/Users/scott/github/iconify/jsx-common/";
#include "JSON.jsxinc";
#include "Utils.jsxinc";
#include "Logger.jsxinc";
#include "Helpers.jsx";
/**
* Name that script.
*/
#script "Save Open Docs";
/**
* Disable Illustrator's alerts.
*/
// Utils.displayAlertsOff();
/**
* Run the script using the Module pattern. This pattern isn't required,
* but it is a nice clean and organized way to write the code. It also avoids
* cluttering the global scope.
*/
var MyModule = (function(CONFIG) {
/**
* The local scope logger object.
* @type {Logger}
*/
var logger = new Logger(CONFIG.APP_NAME, CONFIG.LOGFOLDER);
function doSaveDocs() {
for (i = 0; i < app.documents.length; i++) {
app.activeDocument = app.documents[i];
app.activeDocument.save();
}
}
/**
* Get the current timestamp.
* @returns {number}
* @private
*/
function now() {
return (new Date()).getTime();
}
function getPathItems(src) {
var pathItems = [];
var groupItems = [];
var compoundPathItems = [];
var pageItems = [];
if (isDefined(src.pathItems)) {
pathItems = pathItems.concat(src.pathItems);
$.writeln("src.pathItems : " + src.pathItems.length);
}
if (isDefined(src.pageItems)) {
for (var i = 0; i < src.pageItems.length; i++) {
var thisItem = src.pageItems[i];
pathItems = pathItems.concat(getPathItems(thisItem));
$.writeln("src.pageItems : " + getPathItems(thisItem).length);
}
}
if (isDefined(src.groupItems)) {
for (var i = 0; i < src.groupItems.length; i++) {
var thisItem = src.groupItems[i];
pathItems = pathItems.concat(getPathItems(thisItem));
$.writeln("src.groupItems : " + getPathItems(thisItem).length);
}
}
if (isDefined(src.compoundPathItems)) {
for (var i = 0; i < src.compoundPathItems.length; i++) {
var thisItem = src.compoundPathItems[i];
pathItems = pathItems.concat(getPathItems(thisItem));
$.writeln("src.compoundPathItems : " + getPathItems(thisItem).length);
}
}
return pathItems;
}
function getSource(object) {
try {
object.toSource();
}
catch(e) {
return e.message;
}
}
function getSelectedPathItems() {
var doc = app.activeDocument;
var selected = [],
pathItems = doc.pathItems;
for (var i=0; i 0 ) {
// doSaveDocs();
var doc = app.activeDocument;
// doc.pathItems[0].selected = true;
_selectByUUID('d05fd8b7-7e82-4d3a-b350-cd0866dad6cc');
// $.writeln( getSource(selection) );
// alert( getPathItems(selection).length );
return;
try {
for (x in selection) {
if (typeof(selection[x]) == 'function') continue;
if (selection[x].typename == 'PathItem') {
svgCoords = pathItemToSVG( selection[x] );
$.writeln( svgCoords );
// $.writeln( SVGToPathPointArray( svgCoords ) );
}
}
}
catch(e) {
$.writeln(e);
}
return void(0);
}
else {
alert("There are no open documents");
}
try {
userInteractionLevel = originalInteractionLevel;
}
catch(ex) {/*Exit Gracefully*/}
}
/**
* Returns the public module object/interface.
*/
return {
/**
* Runs the module code.
*/
run: function() {
main();
}
}
})({
APP_NAME : "save-open-docs",
LOGFOLDER : (new Folder($.getenv("HOME"))).absoluteURI + "/ai-logs/"
});
/**
* Run the module.
*/
MyModule.run();
--------------------------------------------------------------------------------
/Smart Layer Export.jsx:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Tom Byrne
2 |
3 | var file;
4 | try{
5 | smartExport = {};
6 |
7 | var classpath = "SmartLayerExport";
8 |
9 | smartExport.appId = "org.tbyrne.smartLayerExport";
10 |
11 | if($.os.toLowerCase().indexOf("macintosh")!=-1){
12 | smartExport.directory = decodeURI(app.path + '/Presets.localized/' + app.locale + "/" + classpath);
13 | }else{
14 | smartExport.directory = decodeURI(app.path + '/Presets/' + app.locale + "/" + classpath);
15 | }
16 | var geo_dynamic = new Folder(smartExport.directory);
17 | var scripts = geo_dynamic.getFiles();
18 |
19 | for(var i=0; i 0 ) {
55 | svgOptions = new ExportOptionsSVG();
56 | svgOptions.embedRasterImages = false;
57 | svgOptions.cssProperties = SVGCSSPropertyLocation.PRESENTATIONATTRIBUTES;
58 | svgOptions.fontSubsetting = SVGFontSubsetting.None;
59 | svgOptions.documentEncoding = SVGDocumentEncoding.UTF8;
60 | svgOptions.coordinatePrecision = 4;
61 |
62 | itemsToExport = [];
63 | sourceDoc = app.activeDocument;
64 | exportFolder = Folder.selectDialog('Select Folder to Save Files');
65 | exportDoc = documents.add( DocumentColorSpace.RGB );
66 |
67 | main();
68 |
69 | exportDoc.close(SaveOptions.DONOTSAVECHANGES);
70 | }
71 | else{
72 | throw new Error('There are no documents open. Open a document and try again.');
73 | }
74 | }
75 | catch(e) {
76 | alert(e.message, "Script Alert", true);
77 | }
78 |
79 | function main() {
80 | var item;
81 | app.activeDocument = sourceDoc;
82 | itemsToExport = getNamedItems(sourceDoc);
83 |
84 | Utils.showProgressBar(itemsToExport.length);
85 |
86 | for ( var i = 0, len = itemsToExport.length; i < len; i++ ) {
87 |
88 |
89 | item = itemsToExport[i];
90 |
91 | Utils.updateProgressMessage( "Exporting item " + item.name );
92 |
93 | if ( item.typename === 'Artboard' ) {
94 | exportArtboard(item);
95 | } else if ( item.typename === 'Layer' ) {
96 | exportLayer(item);
97 | } else {
98 | exportItem(item);
99 | }
100 |
101 | // Empty export document
102 | exportDoc.pageItems.removeAll();
103 |
104 | redraw();
105 |
106 | Utils.updateProgress( item.name + " was exported" );
107 | }
108 |
109 | Utils.progress.close();
110 |
111 | }
112 |
113 | function exportArtboard(artboard) {
114 |
115 | var item,
116 | name,
117 | prettyName,
118 | doc,
119 | rect,
120 | bbox;
121 |
122 | app.activeDocument = sourceDoc;
123 | rect = artboard.artboardRect;
124 |
125 | bbox = sourceDoc.pathItems.rectangle(rect[1], rect[0], rect[2]-rect[0], rect[1]-rect[3]);
126 | bbox.stroked = false;
127 | bbox.name = '__ILSVGEX__BOUNDING_BOX';
128 |
129 | name = artboard.name;
130 | prettyName = name.slice(0, -4).replace(/[^\w\s]|_/g, " ").replace(/\s+/g, "-").toLowerCase();
131 |
132 | app.activeDocument = exportDoc;
133 |
134 | for ( var i = 0, len = sourceDoc.pageItems.length; i < len; i++ ) {
135 | item = sourceDoc.pageItems[i];
136 |
137 | if( hitTest(item, bbox) && !item.locked && !anyParentLocked(item) ) {
138 | item.duplicate( exportDoc, ElementPlacement.PLACEATEND );
139 | }
140 | }
141 |
142 | app.activeDocument = exportDoc;
143 | exportDoc.pageItems.getByName('__ILSVGEX__BOUNDING_BOX').remove();
144 |
145 | // Check if artboard is blank, clean up and exit
146 | if(!exportDoc.pageItems.length) {
147 | sourceDoc.pageItems.getByName('__ILSVGEX__BOUNDING_BOX').remove();
148 | return;
149 | }
150 |
151 | for ( i = 0, len = exportDoc.pageItems.length; i < len; i++) {
152 | item = exportDoc.pageItems[i];
153 |
154 | /*
155 | * For the moment, all pageItems are made visible and exported
156 | * unless they are locked. This may not make sense, but it'll
157 | * work for now.
158 | */
159 | item.hidden = false;
160 | }
161 |
162 | exportDoc.layers[0].name = prettyName;
163 | exportSVG( exportDoc, name, bbox.visibleBounds, svgOptions );
164 |
165 | sourceDoc.pageItems.getByName('__ILSVGEX__BOUNDING_BOX').remove();
166 | }
167 |
168 | function exportLayer(layer) {
169 |
170 | var item,
171 | startX,
172 | startY,
173 | endX,
174 | endY,
175 | name,
176 | prettyName,
177 | itemName,
178 | layerItems;
179 |
180 | layerItems = [];
181 |
182 | for ( var i = 0, len = layer.pageItems.length; i < len; i++ ) {
183 | layerItems.push(layer.pageItems[i]);
184 | }
185 | recurseItems(layer.layers, layerItems);
186 |
187 | if ( !layerItems.length ) {
188 | return;
189 | }
190 |
191 | name = layer.name;
192 | prettyName = name.slice(0, -4).replace(/[^\w\s]|_/g, " ").replace(/\s+/g, "-").toLowerCase();
193 |
194 | for ( i = 0, len = layerItems.length; i < len; i++ ) {
195 | app.activeDocument = sourceDoc;
196 | item = layerItems[i];
197 | item.duplicate( exportDoc, ElementPlacement.PLACEATEND );
198 | }
199 |
200 | app.activeDocument = exportDoc;
201 |
202 | for ( i = 0, len = exportDoc.pageItems.length; i < len; i++) {
203 |
204 | item = exportDoc.pageItems[i];
205 |
206 | /*
207 | * For the moment, all pageItems are made visible and exported
208 | * unless they are locked. This may not make sense, but it'll
209 | * work for now.
210 | */
211 | item.hidden = false;
212 |
213 | if(item.name) {
214 | itemName = item.name;
215 | if(itemName.split('.').pop() === 'svg') {
216 | itemName = itemName.slice(0, -4);
217 | }
218 | itemName = itemName.replace(/[^\w\s]|_/g, " ").replace(/\s+/g, "-").toLowerCase()
219 |
220 | item.name = prettyName + '-' + itemName;
221 | }
222 | /*
223 | * We want the smallest startX, startY for obvious reasons.
224 | * We also want the smallest endX and endY because Illustrator
225 | * Extendscript treats this coordinate reversed to how the UI
226 | * treats it (e.g., -142 in the UI is 142).
227 | *
228 | */
229 | startX = ( !startX || startX > item.visibleBounds[0] ) ? item.visibleBounds[0] : startX;
230 | startY = ( !startY || startY < item.visibleBounds[1] ) ? item.visibleBounds[1] : startY;
231 | endX = ( !endX || endX < item.visibleBounds[2] ) ? item.visibleBounds[2] : endX;
232 | endY = ( !endY || endY > item.visibleBounds[3] ) ? item.visibleBounds[3] : endY;
233 | }
234 |
235 | exportDoc.layers[0].name = name.slice(0, -4);
236 | exportSVG( exportDoc, name, [startX, startY, endX, endY], svgOptions );
237 | }
238 |
239 | function exportItem(item) {
240 |
241 | var name,
242 | newItem;
243 |
244 | name = item.name;
245 | newItem = item.duplicate( exportDoc, ElementPlacement.PLACEATEND );
246 | newItem.hidden = false;
247 | newItem.name = item.name.slice(0, -4);
248 | app.activeDocument = exportDoc;
249 |
250 | exportDoc.layers[0].name = ' ';
251 | exportSVG( exportDoc, name, item.visibleBounds, svgOptions );
252 | }
253 |
254 | function resize(target, scale) {
255 | if (typeof(target.resize) == "function") {
256 | target.resize(
257 | scale,
258 | scale,
259 | true,
260 | true,
261 | true,
262 | true,
263 | scale
264 | );
265 | }
266 | else {
267 |
268 | }
269 | }
270 |
271 |
272 | function centerOnArtboard() {
273 |
274 | var doc = app.activeDocument;
275 | var count = doc.artboards.length;
276 | var __SCALE = 22.222;
277 |
278 | app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
279 |
280 | for (i = 0; i < count; i++) {
281 | doc.artboards.setActiveArtboardIndex(i);
282 | // doc.selection = null;
283 |
284 | var board = doc.artboards[doc.artboards.getActiveArtboardIndex()];
285 | var right = board.artboardRect[2];
286 | var bottom = board.artboardRect[3];
287 |
288 | doc.selectObjectsOnActiveArtboard();
289 |
290 | app.executeMenuCommand('group');
291 |
292 | for (x = 0 ; x < doc.selection.length; x++) {
293 | try {
294 | doc.selection[x].position = [
295 | Math.round((right - doc.selection[x].width)/2),
296 | Math.round((bottom + doc.selection[x].height)/2)
297 | ];
298 |
299 | resize(doc.selection[x], __SCALE);
300 |
301 | resizeArtboard();
302 |
303 | }
304 | catch(e) {
305 | alert(e);
306 | }
307 | }
308 | }
309 |
310 | redraw();
311 | }
312 |
313 | function resizeArtboard() {
314 |
315 | var OPTIONS = {
316 | size : 32,
317 | width : 32,
318 | height : 32
319 | };
320 |
321 | if (app.documents.length > 0) {
322 |
323 | var idoc = app.activeDocument;
324 | var title = "Resize All Artboards";
325 |
326 | OPTIONS.size = "64x64";
327 |
328 | if (OPTIONS.size.indexOf('x') != -1) {
329 | var bits = OPTIONS.size.split('x');
330 | OPTIONS.width = parseInt(bits[0]);
331 | OPTIONS.height = parseInt(bits[1]);
332 | }
333 | else {
334 | OPTIONS.width = OPTIONS.size;
335 | OPTIONS.height = OPTIONS.size;
336 | }
337 |
338 | try {
339 | var width = OPTIONS.width;
340 | var height = OPTIONS.height;
341 |
342 | for (i=0; i 0) {
433 | recurseLayers( layer.layers, layerArray );
434 | }
435 | }
436 | }
437 |
438 | function recurseItems(layers, items) {
439 |
440 | var layer;
441 |
442 | for ( var i = 0, len = layers.length; i < len; i++ ) {
443 | layer = layers[i];
444 | if ( layer.pageItems.length > 0 && !layer.locked ) {
445 | for ( var j = 0, plen = layer.pageItems.length; j < plen; j++ ) {
446 | if ( !layer.pageItems[j].locked ) {
447 | items.push(layer.pageItems[j]);
448 | }
449 | }
450 | }
451 |
452 | if ( layer.layers.length > 0 ) {
453 | recurseItems( layer.layers, items );
454 | }
455 | }
456 | }
457 |
458 | function anyParentLocked(item) {
459 | while ( item.parent ) {
460 | if ( item.parent.locked ) {
461 | return true;
462 | }
463 | item = item.parent;
464 | }
465 |
466 | return false;
467 | }
468 |
469 |
470 | /* Code derived from John Wundes ( john@wundes.com ) www.wundes.com
471 | * Copyright (c) 2005 wundes.com
472 | * All rights reserved.
473 | *
474 | * This code is derived from software contributed to or originating on wundes.com
475 | */
476 |
477 | function hitTest(a,b){
478 | if(!hitTestX(a,b)){
479 | return false;
480 | }
481 | if(!hitTestY(a,b)){
482 | return false;
483 | }
484 | return true;
485 | }
486 |
487 | function hitTestX(a,b){
488 | var p1 = a.visibleBounds[0];
489 | var p2 = b.visibleBounds[0];
490 | if( (p2<=p1 && p1<=p2+b.width) || (p1<=p2 && p2<=p1+a.width) ) {
491 | return true;
492 | }
493 | return false;
494 | }
495 |
496 | function hitTestY(a,b){
497 | var p3 = a.visibleBounds[1];
498 | var p4 = b.visibleBounds[1];
499 | if( (p3>=p4 && p4>=(p3-a.height)) || (p4>=p3 && p3>=(p4-b.height)) ) {
500 | return true;
501 | }
502 | return false;
503 | }
504 |
--------------------------------------------------------------------------------
/copy-layer-name-to-artboard.jsx:
--------------------------------------------------------------------------------
1 | app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
2 |
3 | var doc = activeDocument,
4 | artboard = doc.artboards[doc.artboards.getActiveArtboardIndex()];
5 |
6 | var count = doc.artboards.length;
7 |
8 | try {
9 | if (confirm('Are you sure you want to rename all artboards?')) {
10 | for (var i = 0; i < count; i++) {
11 |
12 | doc.selection = null;
13 |
14 | doc.artboards.setActiveArtboardIndex(i);
15 | artboard = doc.artboards[
16 | doc.artboards.getActiveArtboardIndex()
17 | ];
18 | doc.selectObjectsOnActiveArtboard();
19 |
20 | artboard.name = doc.selection[0].parent.name;
21 | }
22 | }
23 | }
24 | catch(e) {alert(e)}
25 |
26 |
--------------------------------------------------------------------------------
/find-artboards-by-name.jsx:
--------------------------------------------------------------------------------
1 | function find() {
2 |
3 | var doc,
4 | needle;
5 |
6 | doc = activeDocument;
7 |
8 | needle = prompt("Enter a search string", "");
9 |
10 | doc.selection = null;
11 |
12 | try {
13 | for (var i = 0; i < doc.artboards.length; i++) {
14 | if (doc.artboards[i].name.toLowerCase().indexOf(needle) >= 0) {
15 | doc.artboards.setActiveArtboardIndex(i);
16 | doc.selectObjectsOnActiveArtboard();
17 | }
18 | }
19 | }
20 | catch(e) {alert('Error 2 : ' + e)}
21 | }
22 | find();
23 |
--------------------------------------------------------------------------------
/labels.js:
--------------------------------------------------------------------------------
1 | var labels = [
2 | "Black Female Tattooed Person",
3 | "Black Male Tattooed Person",
4 | "White Female Tattooed Person",
5 | "White Male Tattooed Person",
6 | "Asian Female Tattooed Person",
7 | "Asian Male Tattooed Person",
8 | "Black Female Hipsters",
9 | "Black Male Hipsters",
10 | "White Female Hipsters",
11 | "White Male Hipsters",
12 | "Asian Female Hipsters",
13 | "Asian Male Hipsters",
14 | "Black Female Military General",
15 | "Black Male Military General",
16 | "White Female Military General",
17 | "White Male Military General",
18 | "Asian Female Military General",
19 | "Asian Male Military General",
20 | "Black Female Doctor",
21 | "Black Male Doctor",
22 | "White Female Doctor",
23 | "White Male Doctor",
24 | "Asian Female Doctor",
25 | "Asian Male Doctor",
26 | "Black Female Traditional Attire",
27 | "Black Male Traditional Attire",
28 | "White Female Traditional Attire",
29 | "White Male Traditional Attire",
30 | "Asian Female Traditional Attire",
31 | "Asian Male Traditional Attire",
32 | "Black Female Footballers",
33 | "Black Male Footballers",
34 | "White Female Footballers",
35 | "White Male Footballers",
36 | "Asian Female Footballers",
37 | "Asian Male Footballers",
38 | "Black Female Civile Rights Leaders",
39 | "Black Male Civile Rights Leaders",
40 | "White Female Civile Rights Leaders",
41 | "White Male Civile Rights Leaders",
42 | "Asian Female Civile Rights Leaders",
43 | "Asian Male Civile Rights Leaders",
44 | "Black Female Judge/Jurist",
45 | "Black Male Judge/Jurist",
46 | "White Female Judge/Jurist",
47 | "White Male Judge/Jurist",
48 | "Asian Female Judge/Jurist",
49 | "Asian Male Judge/Jurist",
50 | "Black Female Catholic Clergy",
51 | "Black Male Catholic Clergy",
52 | "White Female Catholic Clergy",
53 | "White Male Catholic Clergy",
54 | "Asian Female Catholic Clergy",
55 | "Asian Male Catholic Clergy",
56 | "Black Female Naval Officers",
57 | "Black Male Naval Officers",
58 | "White Female Naval Officers",
59 | "White Male Naval Officers",
60 | "Asian Female Naval Officers",
61 | "Asian Male Naval Officers",
62 | "Black Female eye glasses",
63 | "Black Male eye glasses",
64 | "White Female eye glasses",
65 | "White Male eye glasses",
66 | "Asian Female eye glasses",
67 | "Asian Male eye glasses",
68 | "Black Female senior citizens",
69 | "Black Male senior citizens",
70 | "White Female senior citizens",
71 | "White Male senior citizens",
72 | "Asian Female senior citizens",
73 | "Asian Male senior citizens",
74 | "Black Female Muslim Attire",
75 | "Black Male Muslim Attire",
76 | "White Female Muslim Attire",
77 | "White Male Muslim Attire",
78 | "Asian Female Muslim Attire",
79 | "Asian Male Muslim Attire",
80 | "Black Female EMO",
81 | "Black Male EMO",
82 | "White Female EMO",
83 | "White Male EMO",
84 | "Asian Female EMO",
85 | "Asian Male EMO",
86 | "Black Female french beret",
87 | "Black Male french beret",
88 | "White Female french beret",
89 | "White Male french beret",
90 | "Asian Female french beret",
91 | "Asian Male french beret",
92 | "Black Female surgeon",
93 | "Black Male surgeon",
94 | "White Female surgeon",
95 | "White Male surgeon",
96 | "Asian Female surgeon",
97 | "Asian Male surgeon",
98 | "Black Female nurse",
99 | "Black Male nurse",
100 | "White Female nurse",
101 | "White Male nurse",
102 | "Asian Female nurse",
103 | "Asian Male nurse",
104 | "Black Female graduates",
105 | "Black Male graduates",
106 | "White Female graduates",
107 | "White Male graduates",
108 | "Asian Female graduates",
109 | "Asian Male graduates",
110 | "Black Female private investigator",
111 | "Black Male private investigator",
112 | "White Female private investigator",
113 | "White Male private investigator",
114 | "Asian Female private investigator",
115 | "Asian Male private investigator",
116 | "Black Female Burglar",
117 | "Black Male Burglar",
118 | "White Female Burglar",
119 | "White Male Burglar",
120 | "Asian Female Burglar",
121 | "Asian Male Burglar",
122 | "Robot 1",
123 | "Robot 2",
124 | "Robot 3",
125 | "Robot 4",
126 | "Robot 5",
127 | "Robot 6",
128 | "Black Female teenagers",
129 | "Black Male teenagers",
130 | "White Female teenagers",
131 | "White Male teenagers",
132 | "Asian Female teenagers",
133 | "Asian Male teenagers",
134 | "Black Female police officers",
135 | "Black Male police officers",
136 | "White Female police officers",
137 | "White Male police officers",
138 | "Asian Female police officers",
139 | "Asian Male police officers",
140 | "Black Female hip-hop",
141 | "Black Male hip-hop",
142 | "White Female hip-hop",
143 | "White Male hip-hop",
144 | "Asian Female hip-hop",
145 | "Asian Male hip-hop",
146 | "Black Female chef",
147 | "Black Male chef",
148 | "White Female chef",
149 | "White Male chef",
150 | "Asian Female chef",
151 | "Asian Male chef",
152 | "Black Female farmers",
153 | "Black Male farmers",
154 | "White Female farmers",
155 | "White Male farmers",
156 | "Asian Female farmers",
157 | "Asian Male farmers",
158 | "Black Female Older",
159 | "Black Female Younger",
160 | "White Female Older",
161 | "White Female Younger",
162 | "Asian Female Older",
163 | "Asian Female Younger",
164 | "Black Female eco worker",
165 | "Black Male eco worker",
166 | "White Female eco worker",
167 | "White Male eco worker",
168 | "Asian Female eco worker",
169 | "Asian Male eco worker",
170 | "Black Female airport worker",
171 | "Black Male airport worker",
172 | "White Female airport worker",
173 | "White Male airport worker",
174 | "Asian Female airport worker",
175 | "Asian Male airport worker",
176 | "Black Female repair technician",
177 | "Black Male repair technician",
178 | "White Female repair technician",
179 | "White Male repair technician",
180 | "Asian Female repair technician",
181 | "Asian Male repair technician",
182 | "Black Female actor awards",
183 | "Black Male actor awards",
184 | "White Female actor awards",
185 | "White Male actor awards",
186 | "Asian Female actor awards",
187 | "Asian Male actor awards",
188 | "Black Female disc jockey",
189 | "Black Male disc jockey",
190 | "White Female disc jockey",
191 | "White Male disc jockey",
192 | "Asian Female disc jockey",
193 | "Asian Male disc jockey",
194 | "Black Female big hair",
195 | "Black Male big hair",
196 | "White Female big hair",
197 | "White Male big hair",
198 | "Asian Female big hair",
199 | "Asian Male big hair",
200 | "Black Female road crew",
201 | "Black Male road crew",
202 | "White Female road crew",
203 | "White Male road crew",
204 | "Asian Female road crew",
205 | "Asian Male road crew",
206 | "Black Female anthropologist",
207 | "Black Male anthropologist",
208 | "White Female anthropologist",
209 | "White Male anthropologist",
210 | "Asian Female anthropologist",
211 | "Asian Male anthropologist",
212 | "Black Female construction workers",
213 | "Black Male construction workers",
214 | "White Female construction workers",
215 | "White Male construction workers",
216 | "Asian Female construction workers",
217 | "Asian Male construction workers",
218 | "Black Female plumbers",
219 | "Black Male plumbers",
220 | "White Female plumbers",
221 | "White Male plumbers",
222 | "Asian Female plumbers",
223 | "Asian Male plumbers",
224 | "Black Female senior citizens 2",
225 | "Black Male senior citizens 2",
226 | "White Female senior citizens 2",
227 | "White Male senior citizens 2",
228 | "Asian Female senior citizens 2",
229 | "Asian Male senior citizens 2",
230 | "Black Female accountant",
231 | "Black Male accountant",
232 | "White Female accountant",
233 | "White Male accountant",
234 | "Asian Female accountant",
235 | "Asian Male accountant",
236 | "Black Female airline pilot",
237 | "Black Male airline pilot",
238 | "White Female airline pilot",
239 | "White Male airline pilot",
240 | "Asian Female airline pilot",
241 | "Asian Male airline pilot",
242 | "Black Female nuclear technician",
243 | "Black Male nuclear technician",
244 | "White Female nuclear technician",
245 | "White Male nuclear technician",
246 | "Asian Female nuclear technician",
247 | "Asian Male nuclear technician",
248 | "Black Female average people",
249 | "Black Male average people",
250 | "White Female average people",
251 | "White Male average people",
252 | "Asian Female average people",
253 | "Asian Male average people",
254 | "Black Female average people 2",
255 | "Black Male average people 2",
256 | "White Female average people 2",
257 | "White Male average people 2",
258 | "Asian Female average people 2",
259 | "Asian Male average people 2",
260 | "Black Female engineers",
261 | "Black Male engineers",
262 | "White Female engineers",
263 | "White Male engineers",
264 | "Asian Female engineers",
265 | "Asian Male engineers",
266 | "Black Female baseball caps",
267 | "Black Male baseball caps",
268 | "White Female baseball caps",
269 | "White Male baseball caps",
270 | "Asian Female baseball caps",
271 | "Asian Male baseball caps",
272 | "Black Female gas works",
273 | "Black Male gas works",
274 | "White Female gas works",
275 | "White Male gas works",
276 | "Asian Female gas works",
277 | "Asian Male gas works",
278 | "Black Female police officer 2",
279 | "Black Male police officer 2",
280 | "White Female police officer 2",
281 | "White Male police officer 2",
282 | "Asian Female police officer 2",
283 | "Asian Male police officer 2",
284 | "Black Female bartender",
285 | "Black Male bartender",
286 | "White Female bartender",
287 | "White Male bartender",
288 | "Asian Female bartender",
289 | "Asian Male bartender",
290 | "Black Female butcher",
291 | "Black Male butcher",
292 | "White Female butcher",
293 | "White Male butcher",
294 | "Asian Female butcher",
295 | "Asian Male butcher",
296 | "Black Female movie director",
297 | "Black Male movie director",
298 | "White Female movie director",
299 | "White Male movie director",
300 | "Asian Female movie director",
301 | "Asian Male movie director",
302 | "Black Female designers",
303 | "Black Male designers",
304 | "White Female designers",
305 | "White Male designers",
306 | "Asian Female designers",
307 | "Asian Male designers",
308 | "Black Female Bellhop",
309 | "Black Male Bellhop",
310 | "White Female Bellhop",
311 | "White Male Bellhop",
312 | "Asian Female Bellhop",
313 | "Asian Male Bellhop",
314 | "Black Female hairdresser",
315 | "Black Male hairdresser",
316 | "White Female hairdresser",
317 | "White Male hairdresser",
318 | "Asian Female hairdresser",
319 | "Asian Male hairdresser",
320 | "Black Female scuba diver",
321 | "Black Male scuba diver",
322 | "White Female scuba diver",
323 | "White Male scuba diver",
324 | "Asian Female scuba diver",
325 | "Asian Male scuba diver",
326 | "Black Female photographer",
327 | "Black Male photographer",
328 | "White Female photographer",
329 | "White Male photographer",
330 | "Asian Female photographer",
331 | "Asian Male photographer",
332 | "Black Female mechanic",
333 | "Black Male mechanic",
334 | "White Female mechanic",
335 | "White Male mechanic",
336 | "Asian Female mechanic",
337 | "Asian Male mechanic",
338 | "Black Female fitness trainer",
339 | "Black Male fitness trainer",
340 | "White Female fitness trainer",
341 | "White Male fitness trainer",
342 | "Asian Female fitness trainer",
343 | "Asian Male fitness trainer",
344 | "Black Female blacksmith",
345 | "Black Male blacksmith",
346 | "White Female blacksmith",
347 | "White Male blacksmith",
348 | "Asian Female blacksmith",
349 | "Asian Male blacksmith",
350 | "Black Female disc jockey",
351 | "Black Male disc jockey",
352 | "White Female disc jockey",
353 | "White Male disc jockey",
354 | "Asian Female disc jockey",
355 | "Asian Male disc jockey",
356 | "Black Female baseball caps 2",
357 | "Black Male baseball caps 2",
358 | "White Female baseball caps 2",
359 | "White Male baseball caps 2",
360 | "Asian Female baseball caps 2",
361 | "Asian Male baseball caps 2",
362 | "Black Female Child",
363 | "Black Female Adolescent",
364 | "Black Female Teenager",
365 | "Black Female Adult",
366 | "Black Female Middle Age",
367 | "Black Female Elderly",
368 | "Black Male Child",
369 | "Black Male Adolescent",
370 | "Black Male Teenager",
371 | "Black Male Adult",
372 | "Black Male Middle Age",
373 | "Black Male Elderly",
374 | "White Female Child",
375 | "White Female Adolescent",
376 | "White Female Teenager",
377 | "White Female Adult",
378 | "White Female Middle Age",
379 | "White Female Elderly",
380 | "White Male Child",
381 | "White Male Adolescent",
382 | "White Male Teenager",
383 | "White Male Adult",
384 | "White Male Middle Age",
385 | "White Male Elderly",
386 | "Asian Female Child",
387 | "Asian Female Adolescent",
388 | "Asian Female Teenager",
389 | "Asian Female Adult",
390 | "Asian Female Middle Age",
391 | "Asian Female Elderly",
392 | "Asian Male Child",
393 | "Asian Male Adolescent",
394 | "Asian Male Teenager",
395 | "Asian Male Adult",
396 | "Asian Male Middle Age",
397 | "Asian Male Elderly",
398 | "Black Female Nude",
399 | "Black Female Tee shirt",
400 | "Black Female Tee shirt",
401 | "Black Female Business Casual",
402 | "Black Female Dinner Attire",
403 | "Black Female Formal",
404 | "Black Male Nude",
405 | "Black Male Tee shirt",
406 | "Black Male Hawaiin",
407 | "Black Male Business Casual",
408 | "Black Male Dinner Attire",
409 | "Black Male Formal",
410 | "White Female Nude",
411 | "White Female Tee shirt",
412 | "White Female Tee shirt",
413 | "White Female Business Casual",
414 | "White Female Dinner Attire",
415 | "White Female Formal",
416 | "White Male Nude",
417 | "White Male Tee shirt",
418 | "White male Hawaiin",
419 | "White male Business Casual",
420 | "White male Dinner Attire",
421 | "White male Female Formal",
422 | "Asian Female Nude",
423 | "Asian Female Tee shirt",
424 | "Asian Female Tee shirt",
425 | "Asian Female Business Casual",
426 | "Asian Female Dinner Attire",
427 | "Asian Female Formal",
428 | "Asian Male Nude",
429 | "Asian Male Tee shirt",
430 | "Asian male Hawaiin",
431 | "Asian male Business Casual",
432 | "Asian male Dinner Attire",
433 | "Asian male Female Formal",
434 | "Black Dreadlock Male Nude",
435 | "Black Dreadlock Male Tee shirt",
436 | "Black Dreadlock Male Hawaiin",
437 | "Black Dreadlock Male Business Casual",
438 | "Black Dreadlock Male Dinner Attire",
439 | "Black Dreadlock Male Female Formal",
440 | "Flower Girl 1",
441 | "Flower Girl 2",
442 | "Flower Girl 3",
443 | "Flower Girl 4",
444 | "Flower Girl 5",
445 | "Flower Girl 6",
446 | "Asian Female Hippie Braids",
447 | "Black Male Sideburns",
448 | "Black Female Hat and Shades",
449 | "Rastafarian Male Casual",
450 | "Rastafarian Male Formal",
451 | "White Female Green Hair",
452 | "Black Female punk",
453 | "Black Male punk",
454 | "White Female punk",
455 | "White Male punk",
456 | "Asian Female punk",
457 | "Asian Male punk",
458 | "Black Female EMS worker",
459 | "Black Male EMS worker",
460 | "White Female EMS worker",
461 | "White Male EMS worker",
462 | "Asian Female EMS worker",
463 | "Asian Male EMS worker",
464 | "Black Female construction crew",
465 | "Black Male construction crew",
466 | "White Female construction crew",
467 | "White Male construction crew",
468 | "Asian Female construction crew",
469 | "Asian Male construction crew",
470 | "Black Female farmhand",
471 | "Black Male farmhand",
472 | "White Female farmhand",
473 | "White Male farmhand",
474 | "Asian Female farmhand",
475 | "Asian Male farmhand",
476 | "Black Woman Hair Style 1",
477 | "Black Woman Hair Style 2",
478 | "Black Woman Hair Style 3",
479 | "Black Woman Hair Style 4",
480 | "Black Woman Hair Style 5",
481 | "Black Woman Hair Style 6",
482 | "Black Female tv announcer",
483 | "Black Male tv announcer",
484 | "White Female tv announcer",
485 | "White Male tv announcer",
486 | "Asian Female tv announcer",
487 | "Asian Male tv announcer",
488 | "Black Female firefighter",
489 | "Black Male firefighter",
490 | "White Female firefighter",
491 | "White Male firefighter",
492 | "Asian Female firefighter",
493 | "Asian Male firefighter",
494 | "Black Female artist",
495 | "Black Male artist",
496 | "White Female artist",
497 | "White Male artist",
498 | "Asian Female artist",
499 | "Asian Male artist",
500 | "Black Female cowhand",
501 | "Black Male cowhand",
502 | "White Female cowhand",
503 | "White Male cowhand",
504 | "Asian Female cowhand",
505 | "Asian Male cowhand",
506 | "Black Female fisher",
507 | "Black Male fisher",
508 | "White Female fisher",
509 | "White Male fisher",
510 | "Asian Female fisher",
511 | "Asian Male fisher",
512 | "Black Female network technician",
513 | "Black Male network technician",
514 | "White Female network technician",
515 | "White Male network technician",
516 | "Asian Female network technician",
517 | "Asian Male network technician",
518 | "Black Female jazz singer",
519 | "Black Male jazz musician",
520 | "White Female jazz singer",
521 | "White Male jazz musician",
522 | "Asian Female jazz singer",
523 | "Asian Male jazz musician",
524 | "Black Female old hippies",
525 | "Black Male old hippies",
526 | "White Female old hippies",
527 | "White Male old hippies",
528 | "Asian Female old hippies",
529 | "Asian Male old hippies",
530 | "Black Female young hippies",
531 | "Black Male young hippies",
532 | "White Female young hippies",
533 | "White Male young hippies",
534 | "Asian Female young hippies",
535 | "Asian Male young hippies",
536 | "Black Female asbestos worker",
537 | "Black Male asbestos worker",
538 | "White Female asbestos worker",
539 | "White Male asbestos worker",
540 | "Asian Female asbestos worker",
541 | "Asian Male asbestos worker",
542 | "Black Female daycare worker",
543 | "Black Male daycare worker",
544 | "White Female daycare worker",
545 | "White Male daycare worker",
546 | "Asian Female daycare worker",
547 | "Asian Male daycare worker",
548 | "Black Female house painter",
549 | "Black Male house painter",
550 | "White Female house painter",
551 | "White Male house painter",
552 | "Asian Female house painter",
553 | "Asian Male house painter",
554 | "Black Female pharmacist",
555 | "Black Male pharmacist",
556 | "White Female pharmacist",
557 | "White Male pharmacist",
558 | "Asian Female pharmacist",
559 | "Asian Male pharmacist",
560 | "Black Female chemist",
561 | "Black Male chemist",
562 | "White Female chemist",
563 | "White Male chemist",
564 | "Asian Female chemist",
565 | "Asian Male chemist",
566 | "Black Female stock analyst",
567 | "Black Male stock analyst",
568 | "White Female stock analyst",
569 | "White Male stock analyst",
570 | "Asian Female stock analyst",
571 | "Asian Male stock analyst",
572 | "Black Female carpenter",
573 | "Black Male carpenter",
574 | "White Female carpenter",
575 | "White Male carpenter",
576 | "Asian Female carpenter",
577 | "Asian Male carpenter",
578 | "Black Female computer programmer",
579 | "Black Male computer programmer",
580 | "White Female computer programmer",
581 | "White Male computer programmer",
582 | "Asian Female computer programmer",
583 | "Asian Male computer programmer",
584 | "Black Female building inspector",
585 | "Black Male building inspector",
586 | "White Female building inspector",
587 | "White Male building inspector",
588 | "Asian Female building inspector",
589 | "Asian Male building inspector",
590 | "Black Female stock broker",
591 | "Black Male stock broker",
592 | "White Female stock broker",
593 | "White Male stock broker",
594 | "Asian Female stock broker",
595 | "Asian Male stock broker",
596 | "Black Female cardiopulmonologist",
597 | "Black Male cardiopulmonologist",
598 | "White Female cardiopulmonologist",
599 | "White Male cardiopulmonologist",
600 | "Asian Female cardiopulmonologist",
601 | "Asian Male cardiopulmonologist"
602 | ];
--------------------------------------------------------------------------------
/polyfills.js:
--------------------------------------------------------------------------------
1 | var polyfills = {loaded: true};
2 | /**
3 | * Adds replaceAll method to String
4 | * @param search
5 | * @param replacement
6 | * @returns {string}
7 | */
8 | if (! String.prototype.replaceAll) {
9 | String.prototype.replaceAll = function(search, replacement) {
10 | var target = this;
11 | return target.replace(new RegExp(search, 'g'), replacement);
12 | };
13 | }
14 |
15 | /**
16 | * Adds trim function to the String class.
17 | * @returns {string}
18 | */
19 | if (! String.prototype.trim) {
20 | String.prototype.trim = function () {
21 | return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
22 | };
23 | }
24 |
25 | /**
26 | * Adds a method to star out a string (like a password).
27 | * @returns {string}
28 | */
29 | if (! String.prototype.obfuscate) {
30 | String.prototype.obfuscate = function() {
31 | return this.replace(/./g, "*");
32 | };
33 | }
34 |
35 | if (! Array.prototype.map) {
36 | /**
37 | * Add map method to Array prototype.
38 | * @param fn
39 | */
40 | Array.prototype.map = function(fn) {
41 | for (var i = 0; i < this.length; i++) {
42 | this[i] = fn.call(this, this[i]);
43 | }
44 | return this;
45 | }
46 | }
47 |
48 | /**
49 | * Add Array.indexOf support if not supported natively.
50 | */
51 | if (! Array.prototype.indexOf) {
52 | /**
53 | * Gets the index of an element in an array.
54 | * @param what
55 | * @param i
56 | * @returns {*}
57 | */
58 | Array.prototype.indexOf = function(what, i) {
59 | i = i || 0;
60 | var L = this.length;
61 | while (i < L) {
62 | if(this[i] === what) return i;
63 | ++i;
64 | }
65 | return -1;
66 | };
67 | }
68 |
69 | /**
70 | * Add Array.remove support.
71 | * @returns {Array}
72 | */
73 | Array.prototype.remove = function() {
74 | var what, a = arguments, L = a.length, ax;
75 | while (L && this.length) {
76 | what = a[--L];
77 | while ((ax = this.indexOf(what)) !== -1) {
78 | this.splice(ax, 1);
79 | }
80 | }
81 | return this;
82 | };
83 |
--------------------------------------------------------------------------------
/utils.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 Scott Lewis
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | */
25 |
26 | var Utils = {};
27 |
28 | /**
29 | * Add global progress bar.
30 | */
31 | Utils.progress = {};
32 |
33 | /**
34 | * Get a value from an object or array.
35 | * @param subject
36 | * @param key
37 | * @param _default
38 | * @returns {*}
39 | */
40 | Utils.get = function( subject, key, dfault ) {
41 | var value = dfault;
42 | if (typeof subject == 'object' && subject.hasOwnProperty(key)) {
43 | value = subject[key];
44 | }
45 | return value;
46 | };
47 |
48 |
49 | /**
50 | * Turn off displaying alerts.
51 | */
52 | Utils.displayAlertsOff = function() {
53 | userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
54 | };
55 |
56 | /**
57 | * Turn on displaying alerts.
58 | */
59 | Utils.displayAlertsOn = function() {
60 | try {
61 | userInteractionLevel = UserInteractionLevel.DISPLAYALERTS;
62 | }
63 | catch(e) {/* Exit Gracefully */}
64 | }
65 |
66 | /**
67 | * Gets the screen dimensions and bounds.
68 | * @returns {{left: *, top: *, right: *, bottom: *}}
69 | * ,,-605,263,1893,-1048
70 | */
71 | Utils.getScreenSize = function() {
72 |
73 | try {
74 | if (view = app.activeDocument.views[0] ) {
75 | var zoom = view.zoom;
76 | view.zoom = 1;
77 | var screenSize = {
78 | left : parseInt(view.bounds[0]),
79 | top : parseInt(view.bounds[1]),
80 | right : parseInt(view.bounds[2]),
81 | bottom : parseInt(view.bounds[3]),
82 | width : parseInt(view.bounds[2]) - parseInt(view.bounds[0]),
83 | height : parseInt(view.bounds[1]) - parseInt(view.bounds[3])
84 | };
85 | view.zoom = zoom;
86 | return screenSize;
87 | }
88 | }
89 | catch(e) {/* Exit Gracefully */}
90 | return null;
91 | };
92 |
93 | /**
94 | * Returns a random integer between min (inclusive) and max (inclusive).
95 | * The value is no lower than min (or the next integer greater than min
96 | * if min isn't an integer) and no greater than max (or the next integer
97 | * lower than max if max isn't an integer).
98 | * Using Math.round() will give you a non-uniform distribution!
99 | */
100 | Utils.getRandomInt = function(min, max, omit) {
101 |
102 | var x, num;
103 |
104 | if (typeof(omit) == 'number') omit = [omit];
105 | if (typeof(omit) == 'undefined') omit = [];
106 | min = Math.ceil(min);
107 | max = Math.floor(max);
108 | num = Math.floor(Math.random() * (max - min + 1)) + min;
109 | x = 0;
110 | while (omit.indexOf(num) != -1 && x <= 9999) {
111 | x++;
112 | num = Math.floor(Math.random() * (max - min + 1)) + min;
113 | }
114 | return num;
115 | };
116 |
117 | /**
118 | * Fisher-Yates shuffle an array.
119 | * @link https://www.frankmitchell.org/2015/01/fisher-yates/
120 | * @param array
121 | */
122 | Utils.shuffleArray_1 = function(_array) {
123 | var i = 0,
124 | j = 0,
125 | temp = null;
126 |
127 | for (i = _array.length - 1; i > 0; i--) {
128 | j = Math.floor(Math.random() * (i + 1))
129 | temp = _array[i]
130 | _array[i] = _array[j]
131 | _array[j] = temp
132 | }
133 |
134 | return _array;
135 | };
136 |
137 | Utils.shuffleArray_2 = function(array) {
138 |
139 | var currentIndex = array.length;
140 | var temporaryValue,
141 | randomIndex,
142 | randomValue,
143 | currentValue;
144 |
145 | // While there remain elements to shuffle...
146 | while (0 !== currentIndex) {
147 | // Pick a remaining element...
148 | randomIndex = Math.floor(Math.random() * currentIndex);
149 | currentIndex = currentIndex - 1;
150 |
151 | // And swap it with the current element.
152 | temporaryValue = array[currentIndex];
153 | randomValue = array[randomIndex];
154 | currentValue = array[currentIndex];
155 |
156 | array[currentIndex] = randomValue;
157 | array[randomIndex] = temporaryValue;
158 | }
159 |
160 | return array;
161 |
162 | };
163 |
164 | Utils.knuthShuffle = function(arr) {
165 | var rand, temp, i;
166 |
167 | var len = arr.length - 1;
168 |
169 | for (i = len; i > 0; i--) {
170 | rand = Math.floor((i + 1) * Math.random());//get random between zero and i (inclusive)
171 | temp = arr[rand]; //swap i and the zero-indexed number
172 | arr[rand] = arr[i];
173 | arr[i] = temp;
174 | }
175 | return arr;
176 | };
177 |
178 | /**
179 | * Saves the file in AI format.
180 | * @param {document} doc The document object to save
181 | * @param {string} path The file destination path
182 | * @param {int} aiformat The Adobe Illustrator format (version)
183 | * @return void
184 | */
185 | Utils.saveFileAsAi = function( doc, path, aiformat ) {
186 | if (app.documents.length > 0) {
187 | var theDoc = new File(path);
188 | var options = new IllustratorSaveOptions();
189 | options.compatibility = aiformat;
190 | options.flattenOutput = OutputFlattening.PRESERVEAPPEARANCE;
191 | options.pdfCompatible = true;
192 | doc.saveAs(theDoc, options);
193 | }
194 | };
195 |
196 | /**
197 | *
198 | * @param str
199 | * @returns {XML|string|void}
200 | */
201 | Utils.trim = function(str) {
202 | return str.replace(/^\s+|\s+$/g, '');
203 | };
204 |
205 | /**
206 | * Cleans up the filename/artboardname.
207 | * @param {String} name The name to filter and reformat.
208 | * @returns {String} The cleaned up name.
209 | */
210 | Utils.filterName = function(name) {
211 | return decodeURIComponent(name).replace(' ', '-');
212 | };
213 |
214 | /**
215 | * Sorts a file list.
216 | * @param theList
217 | * @returns {*}
218 | */
219 | Utils.sortFileList = function(theList) {
220 | /**
221 | * Callback for sorting the file list.
222 | * @param {File} a
223 | * @param {File} b
224 | * @returns {number}
225 | */
226 | theList.sort(function (a, b) {
227 | var nameA = Utils.filterName(a.name.toUpperCase());
228 | var nameB = Utils.filterName(b.name.toUpperCase());
229 | if (nameA < nameB) {
230 | return -1;
231 | }
232 | if (nameA > nameB) {
233 | return 1;
234 | }
235 | // names must be equal
236 | return 0;
237 | });
238 | return theList;
239 | };
240 |
241 | /**
242 | * Sort first by set then my file.
243 | * @param fileList
244 | * @returns {*[]}
245 | */
246 | Utils.sortBySetAndName = function(fileList) {
247 |
248 | var sets = {},
249 | keys = [],
250 | sorted = [];
251 |
252 | try {
253 |
254 | for (var i = 0; i < fileList.length; i++) {
255 | var file = fileList[i];
256 | if (keys.indexOf(file.parent.name) == -1) {
257 | keys.push(file.parent.name);
258 | logger('Adding key ' + file.parent.name);
259 | }
260 | }
261 |
262 | keys.sort();
263 |
264 | for (var i = 0; i < keys.length; i++) {
265 | sets[keys[i]] = [];
266 | }
267 |
268 | for (var i = 0; i < fileList.length; i++) {
269 | sets[file.parent.name].push(fileList[i]);
270 | }
271 |
272 | for (setName in sets) {
273 | sets[setName] = Utils.sortFileList(sets[setName]);
274 | sorted = Array.prototype.concat(sorted, sets[setName]);
275 | }
276 | }
277 | catch(e) { alert(e) }
278 |
279 | return sorted;
280 | };
281 |
282 | /**
283 | * Logging for this script.
284 | * @param The logging text
285 | * @return void
286 | */
287 | Utils.logger = function(txt) {
288 |
289 | if (CONFIG.LOGGING == 0) return;
290 | Utils.folder( CONFIG.LOG_FOLDER );
291 | Utils.write_file(CONFIG.LOG_FILE_PATH, "[" + new Date().toUTCString() + "] " + txt);
292 | };
293 |
294 | /**
295 | * Get a unique file name that avoids name colllisions with existing files.
296 | * @param targetFolder
297 | * @param fileName
298 | * @returns {string|*}
299 | */
300 | Utils.getUniqueFileName = function(targetFolder, fileName) {
301 |
302 | var newFile, newFileName;
303 |
304 | newFile = targetFolder + "/" + fileName;
305 |
306 | if (new File(newFile).exists) {
307 | newFileName = Utils.shortUUID() + "@" + fileName;
308 | logger.info(newFileName);
309 | newFile = targetFolderPath + "/" + newFileName;
310 | }
311 |
312 | return newFile;
313 | };
314 |
315 | /**
316 | * Logging for this script.
317 | * @param {string} path The file path
318 | * @param {string} txt The text to write
319 | * @param {bool} replace Replace the file
320 | * @return void
321 | */
322 | Utils.write_file = function( path, txt, replace ) {
323 | try {
324 | var file = new File( path );
325 | if (replace && file.exists) {
326 | file.remove();
327 | file = new File( path );
328 | }
329 | file.open("e", "TEXT", "????");
330 | file.seek(0,2);
331 | $.os.search(/windows/i) != -1 ? file.lineFeed = 'windows' : file.lineFeed = 'macintosh';
332 | file.writeln(txt);
333 | file.close();
334 | return true;
335 | }
336 | catch(ex) {
337 | try {
338 | file.close();
339 | }
340 | catch(ex) {/* Exit Gracefully*/}
341 | throw ex;
342 | }
343 | };
344 |
345 | /**
346 | * Logging for this script.
347 | * @param {string} path The file path
348 | * @param {string} txt The text to write
349 | * @param {bool} replace Replace the file
350 | * @return void
351 | */
352 | Utils.write_and_call = function( path, txt, callback ) {
353 | try {
354 | var file = new File( path );
355 | if (file.exists) {
356 | file.remove();
357 | file = new File( path );
358 | }
359 | file.open("e", "TEXT", "????");
360 | file.seek(0,2);
361 | $.os.search(/windows/i) != -1 ? file.lineFeed = 'windows' : file.lineFeed = 'macintosh';
362 | file.writeln(txt);
363 | file.close();
364 | callback.call(file);
365 | }
366 | catch(ex) {
367 | try {
368 | file.close();
369 | }
370 | catch(ex) {/* Exit Gracefully*/}
371 | throw ex;
372 | }
373 | };
374 |
375 | /**
376 | *
377 | * @param path
378 | * @param json
379 | * @param replace
380 | */
381 | Utils.write_json_file = function( path, json, replace ) {
382 | try {
383 | Utils.write_file(path, Utils.objectToString(json), replace);
384 | }
385 | catch(ex) {
386 | Utils.logger('savePresetsFile - ' + ex);
387 | }
388 | };
389 |
390 | /**
391 | * Reads the contents of a file.
392 | * @param filepath
393 | * @returns {string}
394 | */
395 | Utils.read_file = function( filepath ) {
396 |
397 | var content = "";
398 |
399 | var theFile = new File(filepath);
400 |
401 | if (theFile) {
402 |
403 | try {
404 | if (theFile.alias) {
405 | while (theFile.alias) {
406 | theFile = theFile.resolve().openDlg(
407 | LANG.CHOOSE_FILE,
408 | txt_filter,
409 | false
410 | );
411 | }
412 | }
413 | }
414 | catch(ex) {
415 | dialog.presetsMsgBox.text = ex.message;
416 | }
417 |
418 | try {
419 | theFile.open('r', undefined, undefined);
420 | if (theFile !== '') {
421 | content = theFile.read();
422 | theFile.close();
423 | }
424 | }
425 | catch(ex) {
426 |
427 | try { theFile.close(); }catch(ex){};
428 | logger("read_file - " + ex);
429 | }
430 | }
431 |
432 | return content;
433 | };
434 |
435 | /**
436 | *
437 | * @param filepath
438 | * @returns {*}
439 | */
440 | Utils.read_json_file = function(filepath) {
441 | var contents, result;
442 | try {
443 | if ( contents = Utils.read_file( filepath ) ) {
444 | result = eval("(" + contents + ")" );
445 | if ( typeof(result) != 'object') {
446 | result = null;
447 | }
448 | }
449 | }
450 | catch(ex) {
451 | logger('doUpdatePresets - ' + ex.message);
452 | }
453 | return result;
454 | };
455 |
456 | /**
457 | *
458 | * @param filepath
459 | * @param mustconfirm
460 | */
461 | Utils.deleteFile = function( filepath, mustconfirm ) {
462 | try {
463 | if (mustconfirm && ! confirm(LANG.CONFIRM_DELETE_PRESET)) {
464 | return;
465 | }
466 | new File(filepath).remove();
467 | }
468 | catch(ex) {
469 | Utils.logger('Utils.deleteFile - ' + ex.message);
470 | }
471 | };
472 |
473 | /**
474 | * Initialize a folder.
475 | */
476 | Utils.folder = function( path ) {
477 | var theFolder = new Folder( path );
478 | if (! theFolder.exists) {
479 | theFolder.create();
480 | }
481 | return theFolder;
482 | };
483 |
484 | /**
485 | * Get all files in sub-folders.
486 | * @param srcFolder
487 | * @returns {Array}
488 | */
489 | Utils.getFilesInSubfolders = function( srcFolder ) {
490 |
491 | var allFiles, theFolders, svgFileList;
492 |
493 | if ( ! srcFolder instanceof Folder) return;
494 |
495 | allFiles = srcFolder.getFiles();
496 | theFolders = [];
497 | svgFileList = [];
498 |
499 | for (var x=0; x < allFiles.length; x++) {
500 | if (allFiles[x] instanceof Folder) {
501 | theFolders.push(allFiles[x]);
502 | }
503 | }
504 |
505 | if (theFolders.length == 0) {
506 | svgFileList = srcFolder.getFiles(/\.svg$/i);
507 | }
508 | else {
509 | for (var x=0; x < theFolders.length; x++) {
510 | fileList = theFolders[x].getFiles(/\.svg$/i);
511 | for (var n = 0; n 0) {
632 | for (i = 0; i < selection.length; i++) {
633 | selection[i].moveToEnd(newGroup);
634 | }
635 | }
636 | };
637 |
638 | /**
639 | * Display a new progress bar.
640 | * @param maxvalue
641 | * @returns {*}
642 | */
643 | Utils.showProgressBar = function(maxvalue) {
644 |
645 | var top, right, bottom, left;
646 |
647 | if ( bounds = Utils.getScreenSize() ) {
648 | left = Math.abs(Math.ceil((bounds.width/2) - (450/2)));
649 | top = Math.abs(Math.ceil((bounds.height/2) - (100/2)));
650 | }
651 |
652 | var progress = new Window("palette", 'Progress', [left, top, left + 450, top + 120]);
653 | progress.pnl = progress.add("panel", [10, 10, 440, 100], 'Progress');
654 | progress.pnl.progBar = progress.pnl.add("progressbar", [20, 45, 410, 60], 0, maxvalue);
655 | progress.pnl.progBarLabel = progress.pnl.add("statictext", [20, 20, 320, 35], "0 of " + maxvalue);
656 |
657 | progress.show();
658 |
659 | Utils.progress = progress;
660 | };
661 |
662 | /**
663 | * Hides and destroys the progress bar.
664 | */
665 | Utils.hideProgressBar = function() {
666 | Utils.progress.hide();
667 | Utils.progress = null;
668 | }
669 | /**
670 | * Updates the progress bar.
671 | * @param progress
672 | * @returns {*}
673 | */
674 | Utils.updateProgress = function(message) {
675 | Utils.progress.pnl.progBar.value++;
676 | var val = Utils.progress.pnl.progBar.value;
677 | var max = Utils.progress.pnl.progBar.maxvalue;
678 | Utils.progress.pnl.progBarLabel.text = val + ' of ' + max + ' ' + message;
679 | $.sleep(10);
680 | Utils.progress.update();
681 | };
682 |
683 | /**
684 | * Updates the progress bar.
685 | * @param message
686 | * @returns void(0)
687 | */
688 | Utils.updateProgressMessage = function(message, val, max) {
689 | var val = val || Utils.progress.pnl.progBar.value;
690 | var max = max || Utils.progress.pnl.progBar.maxvalue;
691 | Utils.progress.pnl.progBarLabel.text = val + ' of ' + max + ' ' + message;
692 | $.sleep(10);
693 | Utils.progress.update();
694 | };
695 |
696 | /**
697 | * Updates the progress bar.
698 | * @param message
699 | * @returns void(0)
700 | */
701 | Utils.progressBarText = function(message) {
702 | Utils.progress.pnl.progBarLabel.text = message;
703 | $.sleep(10);
704 | Utils.progress.update();
705 | };
706 |
707 | /**
708 | * Display a new progress bar.
709 | * @param maxvalue
710 | * @returns {*}
711 | */
712 | function showProgressBar(maxvalue) {
713 |
714 | var top, right, bottom, left;
715 |
716 | if ( bounds = Utils.getScreenSize() ) {
717 | left = Math.abs(Math.ceil((bounds.width/2) - (450/2)));
718 | top = Math.abs(Math.ceil((bounds.height/2) - (100/2)));
719 | }
720 |
721 | var progress = new Window("palette", 'Progress', [left, top, left + 450, top + 100]);
722 | progress.pnl = progress.add("panel", [10, 10, 440, 100], 'Progress');
723 | progress.pnl.progBar = progress.pnl.add("progressbar", [20, 35, 410, 60], 0, maxvalue);
724 | progress.pnl.progBarLabel = progress.pnl.add("statictext", [20, 20, 320, 35], "0 of " + maxvalue);
725 |
726 | progress.show();
727 |
728 | return progress;
729 | }
730 |
731 | /**
732 | * Updates the progress bar.
733 | * @param progress
734 | * @returns {*}
735 | */
736 | function updateProgress(progress, message) {
737 | progress.pnl.progBar.value++;
738 | var val = progress.pnl.progBar.value;
739 | var max = progress.pnl.progBar.maxvalue;
740 | progress.pnl.progBarLabel.text = val + ' of ' + max;
741 | $.sleep(10);
742 | progress.update();
743 | return progress;
744 | }
745 |
746 | /**
747 | * Add leading zeros to a number.
748 | * @param {integer} value
749 | * @param {integer} width
750 | * @returns {string}
751 | */
752 | Utils.padNumber = function(value, width) {
753 | return ( value + 100000 ).toString().slice( width * -1 );
754 | };
755 |
756 | /**
757 | * Garbage Collect.
758 | */
759 | Utils.gc = function() {
760 | try {$.gc()}catch(e){}
761 | }
762 |
--------------------------------------------------------------------------------