Copy link to clipboard
Copied
I'd like to to create custom object data in Indesign. I'm not sure if it is possible. I'll use the following example to explain what I'd like to do:
I'd like to be able to put a cirlce at the top of a page in an InDesign document that acts as a reference circle for other objects that I place on that page. I'd then like to run a script to collect the vertical distances from all the objects to the reference circle. Best case senario would be to then have that object data be displayed somewhere with the object within indesign. A not as ideal senario, but satisfactory, would be if a text file was generated with all the objects and there vertical distances from the reference circle.
Is this possible to do in Indesign? Would this be any easier to facilitate in Illusrator?
Thanks in advance,
Ben
Hi @Ben-ind, there isn't any super-handy method that I can think of to do this.
One approach could be to add an event listener (to the document, for example) that would trigger every time the selection changed. It could then add your desired info to the selected item's Script Label panel. A better UI would be to create a CEP panel to show the info, but that is quite a bit more involved unless you've made one before.
Here's a quick example implementation to give you the idea. To help manage t
...Copy link to clipboard
Copied
Sure that's doable. You could name the reference circle in your Layers panel, then for each page in the doc, find page.ovals.itemByName("reference"), then calculate its bounds, then the bounds of other page.ovals that don't share its name. Then populate another named text frame with the values.
Copy link to clipboard
Copied
Yes, but I dont want another named text frame. I want that object data to be stored somewhere with the object, like in the properties tab or something. This is the part that I am finding to be not possible in Indesign. Would you agree?
Going off your proposed soltution, are you able to export text frames as .txt files? That would be the end goal here.
Copy link to clipboard
Copied
You could add it to the oval's label property, or Prototype another property to the Oval object model.
Copy link to clipboard
Copied
Yes you could write data from anywhere in accessible object properties to a txt using the File object.
Copy link to clipboard
Copied
"or Prototype another property to the Oval object model."
What does that mean?
Copy link to clipboard
Copied
Oval.prototype.labelVDistanceToKeyObject = function(key) {
this.label = this.geometricBounds[1] - key.geometricBounds[1];
}
someOval.labelVDistanceToKeyObject(topOval); //now the distance is in some oval's label property
Copy link to clipboard
Copied
Prototypes don't have to be functions. You could have something like:
Oval.prototype.vDistance = "";
///then
someOval.vDistance = (topOval.geometricBounds[1] - someOval.geometricBounds[1]).toString();
Copy link to clipboard
Copied
Hi @Ben-ind, can you give us an example of what the stored data (or txt file written data) would be, for a given sample page? And how do you plan to access it? That will get things moving the quickest I think.
One thing to look into is the "insertLabel" and "extractLabel" functions of many Indesign objects. With, say, myOval.insertLabel(key, value) you could probably achieve what you want. At any time you could do myOval.extractLabel(key) to retrieve the value.
- Mark
Copy link to clipboard
Copied
Here's a simple script that shows what I'm trying to do:
function example() {
// create document
var myDocument = app.documents.add();
myDocument.documentPreferences.pageWidth = "11in";
myDocument.documentPreferences.pageHeight = "8.5in";
myDocument.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.INCHES;
myDocument.viewPreferences.verticalMeasurementUnits = MeasurementUnits.INCHES;
// create reference circle
with (myrefCircle = myDocument.pages.item(0).ovals.add(myDocument.layers.item(0), undefined, undefined, {geometricBounds:[0, 10, 1, 11], strokeWeight: 1, name: "Reference Circle"})) {
myColor_Red = app.activeDocument.colors.add({name:"Red", space:ColorSpace.RGB, colorValue:[255,0,0], colorModel:ColorModel.PROCESS})
mySwatch_Red = myDocument.swatches.item("Red")
myrefCircle.strokeColor = mySwatch_Red
}
// create rectangle at center of page
myRectangle = myDocument.pages.item(0).rectangles.add(myDocument.layers.item(0), undefined, undefined, {geometricBounds:[3.75, 4.5, 4.75, 6.5], strokeWeight: .5, strokeColor: "Black", name: "Rectangle"})
// From here I want to get the vertical distance from top of "Rectangle" to top of "Reference Circle". Thats not difficult.
Vdistance = myrefCircle.geometricBounds[1] - myRectangle.geometricBounds[1]
// I then want that vertical distance to be seen somewhere with "Rectangle" within the Indesign UI if possible. This part I'm unsure of how to do.
// I then want Vdistance to be exported as a text file to the file location of the users choosing. Also unsure of how to do this.
}
app.doScript(example, ScriptLanguage.JAVASCRIPT, [], UndoModes.FAST_ENTIRE_SCRIPT, "Example");
I'm hoping you can fill in the blanks here. I'm having trouble applying protoypes to me example. I'm a bit unclear of what they are.
Copy link to clipboard
Copied
Hi @Ben-ind, there isn't any super-handy method that I can think of to do this.
One approach could be to add an event listener (to the document, for example) that would trigger every time the selection changed. It could then add your desired info to the selected item's Script Label panel. A better UI would be to create a CEP panel to show the info, but that is quite a bit more involved unless you've made one before.
Here's a quick example implementation to give you the idea. To help manage the event listener, I've set it up to alternate between adding and then removing the listener each time you run the script.
- Mark
//@targetengine "SetLabelAsVerticalDistance"
function main() {
var listenerID = 'SetLabelAsVerticalDistance',
referenceCircleID = 'ReferenceCircle',
referenceCircleColorID = 'Red';
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var doc = app.activeDocument;
// get the event listener
var listener = doc.eventListeners.itemByName(listenerID);
// if it exists already, remove it
if (listener.isValid) {
listener.remove();
alert('Event listener "' + listenerID + '" has been removed from document.');
return;
}
else {
// make the event listener
listener = doc.eventListeners.add("afterSelectionChanged", setLabelToDistanceFromVerticalDatum);
listener.name = listenerID;
alert('Event listener "' + listenerID + '" has been added to document.');
}
// the function that will be called by the event listener
function setLabelToDistanceFromVerticalDatum() {
if (doc.selection.length == 0)
return;
var page = doc.layoutWindows[0].activePage;
// get reference circle, if it exists on this page
var referenceCircle = page.pageItems.itemByName(referenceCircleID);
if (
referenceCircle == undefined
|| !referenceCircle.isValid
)
referenceCircle = makeCircle(page);
// I've used the top of the reference circle,
// but you should set this any way you want
var referenceCircleVerticalDatum = referenceCircle.geometricBounds[0];
for (var i = 0; i < doc.selection.length; i++) {
var item = doc.selection[i];
if (item == referenceCircle)
continue;
if (item.hasOwnProperty('geometricBounds'))
// add to the script label (rounded to 3 decimals)
item.label = 'Distance: ' + (Math.round((item.geometricBounds[0] - referenceCircleVerticalDatum) * 1000) / 1000);
}
};
function makeCircle(pg) {
var circle = pg.ovals.add(doc.activeLayer, undefined, undefined, { geometricBounds: [0, 10, 1, 11], strokeWeight: 1, name: referenceCircleID }),
red = doc.colors.itemByName(referenceCircleColorID);
if (!red.isValid)
red = doc.colors.add({ name: referenceCircleColorID, space: ColorSpace.RGB, colorValue: [255, 0, 0], colorModel: ColorModel.PROCESS });
circle.strokeColor = red;
return circle;
};
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Add event listener to set distance from datum');
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more