Copy link to clipboard
Copied
Hi,
In this code sample:
function main()
{
var myImages = app.activeDocument.rectangles, G = myImages.length, // Not necessary!? .everyItem().getElements()
myValue = 0, myIncrementation = -2;
while (G--) {
var myRotation = app.transformationMatrices.add({counterclockwiseRotationAngle: myValue});
myImages
.transform(CoordinateSpaces.pasteboardCoordinates, AnchorPoint.centerAnchor, myRotation); myValue += myIncrementation;
}
}
… use or not use "everyItem().getElements()" seems to not matter!
Does somebody explain this syntax behavior?
Thanks in advance!
(^/)
Copy link to clipboard
Copied
Hi Obi,
I asked the same question a few years ago:
What is the difference between the following two lines?
var myFrame = app.activeDocument.textFrames;
and
var myFrame = app.activeDocument.textFrames.everyItem().getElements();
In both cases the script works as expected. Why do you add .everyItem().getElements()?
Here's what Harbs answered me:
Because everyItem().getElements() builds a static Array of the items.
Without it, it's a dynamic collection.
When you have a collection, there has to be interaction with InDesign
every time you access a member of the collection and InDesign rebuilds
the collection each time it's accessed. That means a lot of extra
overhead.
Bottom line: using a static array is almost always faster than using
collections.
Regards,
Kas
Copy link to clipboard
Copied
Let's illustrate it with example: say, I want to get the list of all the fonts available in InDesign and write it to a text file on the desktop.
var scriptName = "Test";
Main();
function Main() {
var arr = [],
startTime = new Date();
var fonts = app.fonts.everyItem().getElements();
for (var i = 0; i < fonts.length; i++) {
arr.push(fonts.name);
}
var text = arr.join(",");
WriteToFile(text);
var endTime = new Date();
var duration = GetDuration(startTime, endTime);
alert("Elapsed " + duration, scriptName, false);
}
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 WriteToFile(text) {
var file = new File("~/Desktop/" + scriptName + ".txt");
file.encoding = "UTF-8";
file.open("w");
file.write(text);
file.close();
}
function ErrorExit(error, icon) {
alert(error, scriptName, icon);
exit();
}
With .everyItem().getElements() -- using static array -- it takes less than a sec.
if I remove it (use live collection) it takes 9 secs.
— Kas
Copy link to clipboard
Copied
Hi Kas ( ),
Thanks for this instructive comment!
… So, now, I will systematically use "everyItem().getElements()".
(^/)
Copy link to clipboard
Copied
Obi,
But it doesn't mean that you should always use "everyItem().getElements()". In some cases you have to deal with a live collection. For example, recently I wrote this script. It's not the final version, of course, but it will give you an idea. The script dynamically adds new rows (duplicates the product name) at the top of a new page so it should deal with dynamic collection which is updated after a row is added. If you add "everyItem().getElements()", the script will run a little bit faster (maybe), but it's functionality will be totally broken .
— Kas
Copy link to clipboard
Copied
Hi Obi-wan,
some background here that I re-read every now and then and always find new aspects:
Marc Autret:
Indiscripts :: On ‘everyItem()’ – Part 1
Especially Part 2 where getElements() is discussed:
Indiscripts :: On ‘everyItem()’ – Part 2
Regards,
Uwe
Copy link to clipboard
Copied
Thank you for sharing this script. I may found a little typo, since the output was empty. Or did something change in InDesign? best, Thomas
arr.push(fonts[i].name);
Copy link to clipboard
Copied
That error is typical for scripts converted from a different forum software, a few years ago.
The converter ate [i] thinking it meant <i> .
Copy link to clipboard
Copied
Hi Thomas Kaltschmidt@heise , This is an old thread, but I think one advantage of a collection that may not have been covered explicitly, is you don’t always have to loop through a getElements() array in order to get a property list.
You could get all of the document’s font names as an array without using getElements() or looping through the resulting array, something like this:
var f = app.activeDocument.fonts.everyItem().name;
$.writeln(f)
//returns a name array: Acumin Pro Thin,Vista Sans OT Book Italic,Vista Sans OT Book