Copy link to clipboard
Copied
I modified a script created by Kasyan (found here) to serve the purposes of our team. Our workflow involves copywriters placing a tag where scientific figures need to appear within a large document, while those graphic files are still being edited and created by our designers. Since we have a strict naming convention, I switched up the script to find a file that starts with the found text, instead of having to exactly match the file name (since version control will most likely change the file names several times afterwards).
I then made several other modifactions related to layout and design so the placed file would more closely match the end design of our scientific figures. I un-anchored the graphic, added a text frame with a caption based on the file name (for QC and as a placeholder), grouped the caption and image, applied an object style to the group, and re-anchored the group in the same place.
The script ran great MOST of the time, but is glitchy and has lots of different errors that pop up some times, but all of these worked at one point in the process:
Overall my mods seemed to have made the code super glitchy and it is a very unhappy and grumpy script.
I would love some help troubleshooting these errors, and hopefully get some advice or insight on how to make the script more robust and generally happier.
Thank you all so much for your help! If I can get this script to work, then HOURS of finding and placing figure graphics will be saved by members of our team, and we can focus on editing the layout and design with everything we need right there in the document.
//Modified version of the script "Place inline images and fit" found under the following copyright-
/* Copyright 2022, Kasyan Servetsky
October 13, 2022
Written by Kasyan Servetsky
http://www.kasyan.ho.ua
e-mail: askoldich@yahoo.com */
//======================================================================================
var scriptName = "Place Anchored Images at Figure Tags",
debug = false,
imgsExt = /\.jpe*g|psd|png|gif|ai|eps|bmp|tiff*$/i,
doc, set, w, horUnits, verUnits, maxWidth, maxHeight,
foundItems = [],
selectedText = null,
logArr = [],
logErrArr = [],
log = true,
errEditText = false,
logFilePath = "~/Desktop/" + scriptName + " - Log.txt";
var fitOptions = [
FitOptions.APPLY_FRAME_FITTING_OPTIONS,
FitOptions.CENTER_CONTENT,
FitOptions.CONTENT_AWARE_FIT,
FitOptions.CONTENT_TO_FRAME,
FitOptions.FILL_PROPORTIONALLY,
FitOptions.PROPORTIONALLY
];
app.doScript(PreCheck, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.FAST_ENTIRE_SCRIPT, "\"" + scriptName + "\" Script");
//===================================== FUNCTIONS ======================================
function Main() {
try {
var foundItem, file, text, img, container, gb, width, height,
imgFile, imgFiles, figureTagID, story, insPtIndex, pageNumber,
progressWin, progressBar, progressTxt,
imgsFolder = (debug) ? new Folder("~/Desktop/Pictures") : Folder.selectDialog("Choose a folder with images"),
startTime = new Date(),
count = 0;
var progressWin = new Window("window", scriptName);
var progressBar = progressWin.add("progressbar" , undefined, 0, foundItems.length);
progressBar.preferredSize.width = 400;
var progressTxt = progressWin.add("statictext", undefined, "Starting processing classes");
progressTxt.alignment = "fill";
progressWin.show();
if (log) logArr.push("Date & time: " + GetDate() + "\n");
if (imgsFolder != null) {
imgFiles = GetFiles(imgsFolder);
for (var i = 0; i < foundItems.length; i++) {
foundItem = foundItems[i];
figureTagID = foundItem.contents.replace(/@/g, "");
pageNumber = GetPageNumber(foundItem);
if (log) logArr.push((i +1) + ": " + figureTagID + "\tpage: " + ((pageNumber != null) ? pageNumber : "N/A"));
//tried to add on: + "\tfile placed: " + imgFile.displayName .........to the end of this log but it kept throwing the error "undefined is not an object"
story = foundItem.parentStory;
if (set.addPages && story.overflows && foundItem.parent instanceof Cell == false) {
if (debug) $.writeln("The story overflows - AddPages");
AddPages(story);
}
insPtIndex = foundItem.insertionPoints[0].index;
file = new File(imgsFolder.fsName + "/" + figureTagID);
imgFile = GetFile(imgFiles, figureTagID);
progressBar.value = (i + 1);
progressTxt.text = figureTagID;
if (imgFile != null) {
foundItem.remove();
story.recompose();
container = story.insertionPoints[insPtIndex].rectangles.add({strokeWeight: 0});
container.clearObjectStyleOverrides ()
gb = container.geometricBounds;
width = gb[3] - gb[1];
height = gb[2] - gb[0];
container.geometricBounds = [ container.geometricBounds[0],
container.geometricBounds[1],
gb[0] + maxHeight,
gb[3] ];
container.geometricBounds = [ container.geometricBounds[0],
container.geometricBounds[1],
container.geometricBounds[2],
container.geometricBounds[1] + maxWidth ];
img = container.place(imgFile)[0];
if (set.fitOption > 1) {
container.fit(fitOptions[set.fitOption - 2]);
if (set.fitFrameToContents && (set.fitOption == 6 || set.fitOption == 7)) {
container.fit(FitOptions.FRAME_TO_CONTENT);
container.anchoredObjectSettings.releaseAnchoredObject() //this needs to happen so the captions can be grouped with the image
currentStyle=container.appliedObjectStyle
}
}
imgCaption = container.parentPage.textFrames.add();
//set position and size of the caption
imgCaption.geometricBounds = [container.geometricBounds[2] + .75,
container.geometricBounds[1],
container.geometricBounds[2] + .125,
container.geometricBounds[3]];
//add placeholder contents
imgCaption.contents = imgFile.displayName
//group image and caption
var finalFigure = doc.groups.add([container, imgCaption]);
//re-anchor the grouped figure and apply current object style
finalFigure.anchoredObjectSettings.insertAnchoredObject(foundItem.insertionPoints[0]);
finalFigure.applyObjectStyle(currentStyle)
finalFigure.clearObjectStyleOverrides ()
count++;
}
else {
logErrArr.push(figureTagID + " - the file doesn't exist." + " - page " + ((pageNumber != null) ? pageNumber : "N/A"));
}
} // end for
progressWin.close();
var endTime = new Date(),
duration = GetDuration(startTime, endTime);
var report = "Finished. " + count + " image" + ((count == 1) ? " was" : "s were") + " placed.";
if (logErrArr.length > 0) report += " " + logErrArr.length + " error"+ ((logErrArr.length == 1) ? "" : "s") + " occurred."
if (log && logErrArr.length > 0) report += " See the error log on the desktop.";
report += "\rTime elapsed: " + duration;
if (log) {
logArr.push("=========================================================");
logArr.push(count + " image" + ((count == 1) ? " was" : "s were") + " placed.");
logArr.push("Time elapsed: " + duration);
logArr.push("=========================================================");
if (logErrArr.length > 0) {
logArr.push("ERRORS:");
logArr = logArr.concat(logErrArr);
}
logArr.push("\n");
var logTxt = logArr.join("\r");
Log(logTxt, logFilePath, false);
}
if (!debug) {
alert(report, scriptName, false);
}
else {
$.writeln(report);
}
}
}
catch(err) {
if (debug) $.writeln(err.message + ", line: " + err.line);
alert("Critical error: " + err.message + ", line: " + err.line, scriptName, true);
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetPageNumber(txt) {
var result = null;
try {
var pageName = txt.parentTextFrames[0].parentPage.name;
result = pageName;
}
catch(err) {
if (debug) $.writeln(err.message + ", line: " + err.line);
}
return result;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function CreateDialog() {
var etWidth = 4,
fitOptionsList = [
"Don't fit",
"-",
"Use frame fitting options",
"Center content",
"Content-aware fit",
"Fit content to frame",
"Fill frame proportionally",
"Fit content proportionally"
];
w = new Window("dialog", scriptName); // global
w.add("statictext", undefined, "HEY THERE! \nDouble check that the currently selected Paragraph and Object Styles are the ones you want to use.", {multiline: true})
w.p = w.add("panel", undefined, "");
w.p.orientation = "column";
w.p.alignment = "fill";
w.p.alignChildren = "right";
w.p.g = w.p.add("group");
w.p.g.orientation = "row";
w.p.g.st = w.p.g.add("statictext", undefined, "Max. width:");
w.p.g.et = w.p.g.add("edittext", undefined, maxWidth);
w.p.g.et.characters = etWidth;
w.p.g.et.onChange = CheckValue;
w.p.g.st1 = w.p.g.add("statictext", undefined, GetAbrigedUnits(true));
w.p.g1 = w.p.add("group");
w.p.g1.orientation = "row";
w.p.g1.st = w.p.g1.add("statictext", undefined, "Max. height:");
w.p.g1.et = w.p.g1.add("edittext", undefined, maxHeight);
w.p.g1.et.characters = etWidth;
w.p.g1.et.onChange = CheckValue;
w.p.g1.st1 = w.p.g1.add("statictext", undefined, GetAbrigedUnits(false));
w.p.dll = w.p.add("dropdownList", undefined, fitOptionsList);
w.p.dll.selection = set.fitOption;
w.p.dll.onChange = function() {
if (this.selection.index == 6 || this.selection.index == 7) {
w.p.cb.enabled = true;
}
else {
w.p.cb.enabled = false;
}
}
w.p.cb = w.p.add("checkbox", undefined, "Fit frame to contents");
w.p.cb.value = set.fitFrameToContents;
w.p.cb.helpTip = "After 'Fill/fit frame proportionally', as an extra step, fit content to frame.";
if (set.fitOption == 6 || set.fitOption == 7) {
w.p.cb.enabled = true;
}
else {
w.p.cb.enabled = false;
}
w.p.cb1 = w.p.add("checkbox", undefined, "Make log file on the desktop");
w.p.cb1.value = set.makeLog;
w.p.cb2 = w.p.add("checkbox", undefined, "Add pages if text overflows");
w.p.cb2.value = set.addPages;
w.p.cb2.helpTip = "If the text overflows, as many as necessary pages will be added at the end of the document.";
w.st = w.add("statictext", undefined, ("Process " + foundItems.length + " tag" + ((foundItems.length > 1) ? "s" : "") + " in the " + ((selectedText == null) ? "whole document" : "selected text")));
w.st.alignment = "center";
w.st.helpTip = "Select some text or a text frame to process only this selection; otherwise, the whole document will be processed.";
// Buttons
w.bts = w.add("group");
w.bts.orientation = "row";
w.bts.alignment = "center";
w.bts.ok = w.bts.add("button", undefined, "OK", {name:"ok"});
w.bts.ok.onClick = function() {
if (errEditText) {
errEditText = false;
return;
}
w.close(1);
}
w.bts.cancel = w.bts.add("button", undefined, "Cancel", {name:"cancel"});
var showDialog = w.show();
if (showDialog == 1) {
maxWidth = Number(w.p.g.et.text);
maxHeight = Number(w.p.g1.et.text);
eval("set.maxWidth_" + horUnits + " = Number(w.p.g.et.text)");
eval("set.maxHeight_" + verUnits + " = Number(w.p.g1.et.text)");
set.fitOption = w.p.dll.selection.index;
set.fitFrameToContents = w.p.cb.value;
set.addPages = w.p.cb2.value;
app.insertLabel(scriptName, set.toSource());
Main();
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function CheckValue() {
this.text = this.text.replace(",", ".");
var fieldName = this.parent.children[0].text;
if (this.text == "") {
alert(fieldName + " should not be empty.", scriptName, true);
this.text = (fieldName == "Max. width:") ? maxWidth : maxHeight;
errEditText = true;
}
else if (this.text == "0") {
alert(fieldName + " should not be zero.", scriptName, true);
this.text = (fieldName == "Max. width:") ? maxWidth : maxHeight;
errEditText = true;
}
else if (isNaN(this.text)) {
alert(fieldName + " is not a number.", scriptName, true);
this.text = (fieldName == "Max. width:") ? maxWidth : maxHeight;
errEditText = true;
}
0
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetDialogSettings() {
set = eval(app.extractLabel(scriptName));
if (set == undefined) {
set = {
fitOption: 0,
fitFrameToContents: false,
makeLog: true,
addPages: false,
maxWidth_POINTS: 85,
maxHeight_POINTS: 57,
maxWidth_PICAS: 7,
maxHeight_PICAS: 5,
maxWidth_INCHES: 1.2,
maxHeight_INCHES: 0.8,
maxWidth_INCHES_DECIMAL: 1.2,
maxHeight_INCHES_DECIMAL: 0.8,
maxWidth_MILLIMETERS: 30,
maxHeight_MILLIMETERS: 20,
maxWidth_CENTIMETERS: 3,
maxHeight_CENTIMETERS: 2,
maxWidth_CICEROS: 7,
maxHeight_CICEROS: 5,
maxWidth_AGATES: 17,
maxHeight_AGATES: 11,
maxWidth_PIXELS: 85,
maxHeight_PIXELS: 57,
maxWidth_CUSTOM: 85,
maxHeight_CUSTOM: 57
};
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function FindTags() {
app.findGrepPreferences = app.changeGrepPreferences = NothingEnum.NOTHING;
app.findGrepPreferences.findWhat = "@.+?@";
if (selectedText != null) {
foundItems = selectedText.findGrep(true);
}
else {
foundItems = doc.findGrep(true);
}
app.findGrepPreferences = app.changeGrepPreferences = NothingEnum.NOTHING;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetFile(files, name) {
var file = null;
for (var i = 0; i < files.length; i++) {
if (files[i].displayName.toLowerCase().indexOf(name.toLowerCase()) == 0) {
// files[i] starts with name
return files[i];
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetFiles(theFolder) {
var files = [],
fileList = theFolder.getFiles(),
i, file;
for (i = 0; i < fileList.length; i++) {
file = fileList[i];
if (file instanceof Folder) {
files = files.concat(GetFiles(file));
}
else if (file instanceof File && file.name.match(imgsExt)) {
files.push(file);
}
}
return files;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function Log(text, path, newLine) {
if (typeof variable == "newLine") newLine = false;
if (newLine) text += "\n";
file = new File(path);
file.encoding = "UTF-8";
if (file.exists) {
file.open("e");
file.seek(0, 2);
}
else {
file.open("w");
}
file.write(text);
file.close();
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function PreCheck() {
if (app.documents.length == 0) ErrorExit("Please open a document and try again.", true);
doc = app.activeDocument;
if (doc.converted) ErrorExit("The current document has been modified by being converted from older version of InDesign. Please save the document and try again.", true);
if (!doc.saved) ErrorExit("The current document has not been saved since it was created. Please save the document and try again.", true);
if (app.selection.length == 1) {
var sel = app.selection[0];
if (sel.hasOwnProperty("baseline") && sel instanceof InsertionPoint == false) { // text selected
selectedText = sel;
}
else if (sel instanceof TextFrame) { // text frame selected
selectedText = sel.texts[0];
}
}
FindTags();
if (foundItems == 0) {
ErrorExit("No tags were found in the " + ((selectedText == null) ? "document." : "selected text."), true);
}
GetDialogSettings();
horUnits = String(doc.viewPreferences.horizontalMeasurementUnits);
verUnits = String(doc.viewPreferences.verticalMeasurementUnits);
maxWidth = eval("set.maxWidth_" + horUnits),
maxHeight = eval("set.maxHeight_" + verUnits);
CreateDialog();
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function ErrorExit(error, icon) {
alert(error, scriptName, icon);
exit();
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function AddPages(story) {
var textFrame = story.textContainers[0],
newPage, gb, newTextFrame, currentTextFrame,
currentPage = textFrame.parentPage;
while (story.overflows) {
newPage = doc.pages.add(LocationOptions.AFTER, currentPage);
currentPage = newPage;
gb = GetBounds(currentPage);
newTextFrame = currentPage.textFrames.add({geometricBounds: gb});
textFrame.nextTextFrame = newTextFrame;
textFrame = newTextFrame;
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetBounds(page) {
var X1, X2, Y1, Y2,
pageWidth = doc.documentPreferences.pageWidth,
pageHeight = doc.documentPreferences.pageHeight;
if (page.side == PageSideOptions.LEFT_HAND || page.side == PageSideOptions.SINGLE_SIDED) {
X1 = page.marginPreferences.right;
X2 = pageWidth - page.marginPreferences.left;
}
else if (page.side == PageSideOptions.RIGHT_HAND) {
X1 = page.marginPreferences.left + pageWidth;
X2 = pageWidth * 2 - page.marginPreferences.right;
}
Y1 = page.marginPreferences.top;
Y2 = pageHeight - page.marginPreferences.bottom;
return [Y1, X1, Y2, X2];
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetDuration(startTime, endTime) {
var str;
var duration = (endTime - startTime)/1000;
duration = Math.round(duration);
if (duration >= 60) {
var minutes = Math.floor(duration/60);
var seconds = duration - (minutes * 60);
str = minutes + ((minutes != 1) ? " minutes, " : " minute, ") + seconds + ((seconds != 1) ? " seconds" : " second");
if (minutes >= 60) {
var hours = Math.floor(minutes/60);
minutes = minutes - (hours * 60);
str = hours + ((hours != 1) ? " hours, " : " hour, ") + minutes + ((minutes != 1) ? " minutes, " : " minute, ") + seconds + ((seconds != 1) ? " seconds" : " second");
}
}
else {
str = duration + ((duration != 1) ? " seconds" : " second");
}
return str;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetDate() {
var date = new Date();
if ((date.getYear() - 100) < 10) {
var year = "0" + new String((date.getYear() - 100));
}
else {
var year = new String((date.getYear() - 100));
}
var dateString = (date.getMonth() + 1) + "/" + date.getDate() + "/" + year + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
return dateString;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetAbrigedUnits(horizontal) {
var ruler,
result = "";
if (horizontal) {
ruler = "horizontal";
}
else {
ruler = "vertical";
}
if (eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.POINTS") || eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.CUSTOM") ) {
result = "pt";
}
else if (eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.PICAS")) {
result = "p";
}
else if (eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.INCHES") || eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.INCHES_DECIMAL")) {
result = "in";
}
else if (eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.MILLIMETERS")) {
result = "mm";
}
else if (eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.CENTIMETERS")) {
result = "cm";
}
else if (eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.CICEROS")) {
result = "c";
}
else if (eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.AGATES")) {
result = "ag";
}
else if (eval("doc.viewPreferences." + ruler + "MeasurementUnits == MeasurementUnits.PIXELS")) {
result = "px";
}
return result;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
Have something to add?