Hey All, hopefully found a place where I can get this figured out. I use Specify in illustrator 2024 at work and CS3 at home. I realize CS3 is older, but I want to use it-if possible . I get the top feature to work, but doesnt allow me to access left, right, bottom, etc. Any help would be greatly appreciated!
/* ======================================
- GitHub - adamdehaven/specify: An extension used to automate specifying dimensions (and adding dimension lines) of objects in Adobe Illustrator
- Adam Dehaven ( @adamdehaven )
- http://adamdehaven.com/
- ======================================
*/
if (app.documents.length > 0) {
// Create empty dialog window
var specifyDialogBox = new Window('dialog', 'Specify');
specifyDialogBox.frameLocation = [500,400];
specifyDialogBox.size = [350,150];
specifyDialogBox.intro = specifyDialogBox.add('statictext', [20,10,310,50] );
specifyDialogBox.intro.text = 'Select which dimension to specify:';
specifyDialogBox.where = specifyDialogBox.add('dropdownlist', [20,50,100,40] );
specifyDialogBox.where.selection = specifyDialogBox.where.add('item', 'Top');
specifyDialogBox.where.add('item', 'Right');
specifyDialogBox.where.add('item', 'Bottom');
specifyDialogBox.where.add('item', 'Left');
specifyDialogBox.units = specifyDialogBox.add('checkbox', [140,54,300,90], 'Include units label');
specifyDialogBox.units.value = true;
specifyDialogBox.btn = specifyDialogBox.add('button', [140,100,280,140], 'Specify Object(s) ▸', 'spec');
// document
var doc = activeDocument;
// count selected items
var selectedItems = parseInt( doc.selection.length ) || 0;
// spec layer
try {
var specsLayer = doc.layers['SPECS'];
} catch(err) {
var specsLayer = doc.layers.add();
specsLayer.name = 'SPECS';
}
// measurement line and text color in RGB
var color = new RGBColor;
color.red = 255;
color.green = 51;
color.blue = 255;
// gap between measurement lines and object
var gap = 2;
// size of perpendicular measurement lines.
var size = 6;
// number of decimal places in measurement
var decimals = 3;
// pixels per inch
var dpi = 300;
/**
Start the spec
*/
function startSpec() {
if (selectedItems == 1) {
specSingle( doc.selection[0].geometricBounds, specifyDialogBox.where.selection.text );
} else if (selectedItems == 2) {
specDouble( doc.selection[0], doc.selection[1], specifyDialogBox.where.selection.text );
} else {
alert('Please select at least 1 or 2 items.');
}
specifyDialogBox.close();
}
/**
Spec the gap between 2 elements
*/
function specDouble( item1, item2, where ) {
var bound = new Array(0,0,0,0);
var a = item1.geometricBounds;
var b = item2.geometricBounds;
if (where=='Top' || where=='Bottom') {
if (b[0]>a[0]) { // item 2 on right,
if (b[0]>a[2]) { // no overlap
bound[0] =a[2];
bound[2] = b[0];
} else { // overlap
bound[0] =b[0];
bound[2] = a[2];
}
} else if (a[0]>=b[0]){ // item 1 on right
if (a[0]>b[2]) { // no overlap
bound[0] =b[2];
bound[2] = a[0];
} else { // overlap
bound[0] =a[0];
bound[2] = b[2];
}
}
bound[1] = Math.max (a[1], b[1]);
bound[3] = Math.min (a[3], b[3]);
} else {
if (b[3]>a[3]) { // item 2 on top
if (b[3]>a[1]) { // no overlap
bound[3] =a[1];
bound[1] = b[3];
} else { // overlap
bound[3] =b[3];
bound[1] = a[1];
}
} else if (a[3]>=b[3]){ // item 1 on top
if (a[3]>b[1]) { // no overlap
bound[3] =b[1];
bound[1] = a[3];
} else { // overlap
bound[3] =a[3];
bound[1] = b[1];
}
}
bound[0] = Math.min(a[0], b[0]);
bound[2] = Math.max (a[2], b[2]);
}
specSingle(bound, where );
}
/**
spec a single object
@param bound item.geometricBound
@param where 'Top', 'Right', 'Bottom,' 'Left'
*/
function specSingle( bound, where ) {
specsLayer.locked = false;
// width and height
var w = bound[2]-bound[0];
var h = bound[1]-bound[3];
// a & b are the horizontal or vertical positions that change
// c is the horizontal or vertical position that doesn't change
var a = bound[0];
var b = bound[2];
var c = bound[1];
// xy='x' (horizontal measurement), xy='y' (vertical measurement)
var xy = 'x';
// a direction flag for placing the measurement lines.
var dir = 1;
switch( where ) {
case 'Top':
a = bound[0];
b = bound[2];
c = bound[1];
xy = 'x';
dir = 1;
break;
case 'Right':
a = bound[1];
b = bound[3];
c = bound[2];
xy = 'y';
dir = 1;
break;
case 'Bottom':
a = bound[0];
b = bound[2];
c = bound[3];
xy = 'x';
dir = -1;
break;
case 'Left':
a = bound[1];
b = bound[3];
c = bound[0];
xy = 'y';
dir = -1;
break;
}
// create the measurement lines
var lines = new Array();
// horizontal measurement
if (xy=='x') {
// 2 vertical lines
lines[0]= new Array( new Array(a, c+(gap)*dir) );
lines[0].push ( new Array(a, c+(gap+size)*dir) );
lines[1]= new Array( new Array(b, c+(gap)*dir) );
lines[1].push( new Array(b, c+(gap+size)*dir) );
// 1 horizontal line
lines[2]= new Array( new Array(a, c+(gap+size/2)*dir ) );
lines[2].push( new Array(b, c+(gap+size/2)*dir ) );
// create text label
if (where=='Top') {
var t = specLabel( w, (a+b)/2, lines[0][1][1], color );
t.top += t.height;
} else {
var t = specLabel( w, (a+b)/2, lines[0][0][1], color );
t.top -= t.height;
}
t.left -= t.width/2;
// vertical measurement
} else {
// 2 horizontal lines
lines[0]= new Array( new Array( c+(gap)*dir, a) );
lines[0].push ( new Array( c+(gap+size)*dir, a) );
lines[1]= new Array( new Array( c+(gap)*dir, b) );
lines[1].push( new Array( c+(gap+size)*dir, b) );
//1 vertical line
lines[2]= new Array( new Array(c+(gap+size/2)*dir, a) );
lines[2].push( new Array(c+(gap+size/2)*dir, b) );
// create text label
if (where=='Left') {
var t = specLabel( h, lines[0][1][0], (a+b)/2, color );
t.left -= t.width;
} else {
var t = specLabel( h, lines[0][0][0], (a+b)/2, color );
t.left += size;
}
t.top += t.height/2;
}
// draw the lines
var specgroup = new Array(t);
for (var i=0; i<lines.length; i++) {
var p = doc.pathItems.add();
p.setEntirePath ( lines[i] );
setLineStyle( p, color );
specgroup.push( p );
}
group(specsLayer, specgroup );
specsLayer.locked = true;
}
/**
Create a text label that specify the dimension
*/
function specLabel( val, x, y, color) {
var t = doc.textFrames.add();
t.textRange.characterAttributes.size = 8;
t.textRange.characterAttributes.alignment = StyleRunAlignmentType.center;
t.textRange.characterAttributes.fillColor = color;
// Conversions : http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/illustrator/sdk/CC2014/Illustrator%20Scripting%20Guide.pdf
// UnitValue object (page 230): http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/scripting/pdfs/javascript_tools_guide.pdf
var displayUnitsLabel = specifyDialogBox.units.value;
var v = val;
var unitsLabel = '';
switch (doc.rulerUnits) {
case RulerUnits.Picas:
v = new UnitValue(v, "pt").as("pc");
var vd = v - Math.floor (v);
vd = 12*vd;
v = Math.floor(v)+'p'+vd.toFixed (decimals);
break;
case RulerUnits.Inches:
v = new UnitValue(v, "pt").as("in");
v = v.toFixed (decimals);
unitsLabel = " in"; // add abbreviation
break;
case RulerUnits.Millimeters:
v = new UnitValue(v, "pt").as("mm");
v = v.toFixed (decimals);
unitsLabel = " mm"; // add abbreviation
break;
case RulerUnits.Centimeters:
v = new UnitValue(v, "pt").as("cm");
v = v.toFixed (decimals);
unitsLabel = " cm"; // add abbreviation
break;
case RulerUnits.Pixels:
v = new UnitValue(v, "pt").as("px");
v = v.toFixed (decimals);
unitsLabel = " px"; // add abbreviation
break;
default:
v = new UnitValue(v, "pt").as("pt");
v = v.toFixed (decimals);
unitsLabel = " pt"; // add abbreviation
}
if(displayUnitsLabel) {
t.contents = v + unitsLabel;
} else {
t.contents = v;
}
t.top = y;
t.left = x;
return t;
}
function setLineStyle(path, color) {
path.filled = false;
path.stroked = true;
path.strokeColor = color;
path.strokeWidth = 0.5;
return path;
}
/**
* Group items in a layer
*/
function group( layer, items, isDuplicate) {
// create new group
var gg = layer.groupItems.add();
// add to group
// reverse count, because items length is reduced as items are moved to new group
for(var i=items.length-1; i>=0; i--) {
if (items[i]!=gg) { // don't group the group itself
if (isDuplicate) {
newItem = items[i].duplicate (gg, ElementPlacement.PLACEATBEGINNING);
} else {
items[i].move( gg, ElementPlacement.PLACEATBEGINNING );
}
}
}
return gg;
}
/*
** ======================================
** RUN SCRIPT
** ======================================
*/
switch (selectedItems) {
case 0:
beep();
alert('Please select 1 or 2 items and try again.');
break;
case 1:
case 2:
specifyDialogBox.btn.addEventListener ('click', startSpec );
specifyDialogBox.show();
break;
default:
beep();
alert('You have more than 2 items selected. \nPlease select only 1 or 2 items and try again.');
break;
}
} else { // No active document
alert(‘There are no objects to Specify. \nPlease open a document.’)
}