• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

allPageItems returns 0

Engaged ,
Feb 21, 2017 Feb 21, 2017

Copy link to clipboard

Copied

Hi,

I have one text frame with a word inside it on a layer called "Draft".

When I call:

var y = app.activeDocument.layers.itemByName( "Draft" );

alert( y.textFrames.length );

I always get 0.

Any idea why that is?

It's the same for textFrames.length.

TOPICS
Scripting

Views

1.9K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Feb 21, 2017 Feb 21, 2017

Hi Jake,

for details see also this discussion from 5 years ago:

[JSX] Bug in property "allPageItems" of object "layer"?

Regards,
Uwe

Votes

Translate

Translate
Engaged ,
Feb 21, 2017 Feb 21, 2017

Copy link to clipboard

Copied

I mean it's the same for allPageItems

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 21, 2017 Feb 21, 2017

Copy link to clipboard

Copied

Hi Jake,

is the textFrame positioned on a master spread on a layer named "Draft" ?

Then indeed:

app.documents[0].layers.itemByName("Draft").allPageItems.length

will return 0

Wheras:

app.documents[0].allPageItems.length

should return at least 1

Years ago we had a discussion about this here in the forum.

Some say it's a bug, some say it's as designed.

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 21, 2017 Feb 21, 2017

Copy link to clipboard

Copied

Hi Jake,

for details see also this discussion from 5 years ago:

[JSX] Bug in property "allPageItems" of object "layer"?

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

Thanks Laubender​. You're right the text frame is on a master spread.

It definitely was confusing but the discussion was a great help!

I'll use your suggestion of:

1. check if: doc.mylayer.pageItems.length = 0

2. loop through all pageItems on master pages and looking if the itemLayer property is equal to the particular layer we want to remove

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

Yes, I was also confused back then after detecting that.

Glad I could help.

Regards,

Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

Hi Laubender,

I tried the following:

var doc = app.activeDocument;

var myLayer = doc.layers.itemByName( "Draft" );

alert(myLayer.name);

if ( myLayer.pageItems.length === 0 ) {

               

    var masterItems = doc.masterSpreads.everyItem().pageItems;

              

           for (var i = 0; i < masterItems.length; i++ ) {

              

                 alert (masterItems.itemLayer.name )

                

                        if ( masterItems.itemLayer.name === myLayer.name ) {

       

                            alert ("found it")

                           

                            break;

                           

                            }

                        }

                    }

The variable masterItems holds an array of pageItems but the name property is always undefined.

Any idea why?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

jakec88782761  wrote

… Any idea why?

Yes.

Resolve your page items with getElements() .

That means address the concrete object—in your cae a textFrame—that is behind the pageItem.

Your code:

masterItems.itemLayer.name

// Result: Undefined

Resolving the page item:

// Resolving with getElements()

masterItems.getElements()[0].itemLayer.name

// Result: Draft

Best read about "On everyItem()" by Marc Autret:

Indiscripts :: On ‘everyItem()’ – Part 1

Indiscripts :: On ‘everyItem()’ – Part 2

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

Hi Jakec

(…)

The variable masterItems holds an array of pageItems (…)

Nope, it doesn't. As defined, your variable masterItems holds a PageItems object, that is, a collection.

What you want is

// ...

var masterItems = doc.masterSpreads.everyItem().pageItems.everyItem().getElements();

// ...

and then your code will work.

But your mistake is interesting to study. Your original assignment,

// ...

var masterItems = doc.masterSpreads.everyItem().pageItems;

// ...

leads to an object (typeof masterItems == "object") whose actual class is PageItems. In other words, (masterItems instanceof PageItems) == true. We know that PageItems is a collection, not an array. That kind of object exposes a length property though, returning the count of underlying elements (myCollection.length is equivalent to myCollection.count().)

But what is the interesting fact here? Well, you formed this PageItems (single) object from a syntax that embeds the famous everyItem() command, which is known to make up a plural specifier. Usually, adding a property after a plural specifier creates an array. So one could have expected …everyItem().pageItems to be an “array of PageItems collections,” which it is not. Furthermore …everyItem().pageItems is not a specifier either. Maybe we may call it an "incomplete specifier" in the sense that it just opens a branch in the path and is still waiting for something next to finalize an actual specifier. A simple way to prove that your masterItems is not a specifier—apart from the fact that it is a collection!—is checking the unavailability of masterItems.toSpecifier(). (=> Runtime error)

Anyway, and that's the point I wanted to highlight, masterItems.toSource() results in the string 'resolve("/document[@id=1]/master-spread/page-item")', which exactly contains the path that masterItems.everyItem().toSpecifier() would have shown before resolution. Intriguing, is not it? In addition, masterItems.count() returns the correct number of items that one will access using the complete syntax, meaning that this weird PageItems collection already integrates the effect of masterSpreads.everyItem() used upstream. I wasn't well aware of this phenomenon before considering this example, so, thanks for your typo 😉

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

Thanks for the explanation Marc, I had a look at your blog posts about everyItem() and it was an interesting read.

One thing that does confuse me though:

var masterItems = doc.masterSpreads.everyItem().pageItems.everyItem().length

gives me an error "object does not support the property length. Even though there are 3 page items.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

Thank you for the details, Marc.

Hi Jake,

I'm running your script with the ESTK on a document with 3 master spreads where a text frame is added to layer "Draft" on the 3rd master spread. I am doing a break point just before the loop through the masteritems.

JavaScriptConsole-ESTK-inspecting-masterItems.png

Then I ask the Console some things by typing to it.
Hit return and the Console is answering with an immediate result.

masterItems

Result: [object PageItems]

// Note the plural s : [object PageItems]

masterItems.constructor.name

Result: PageItems

// Note the plural s : PageItems

masterItems.count()

Result: 0,0,1

// No pageItem on master 1 and 2. One pageItem on master 3.

masterItems.count().constructor.name

Result: Array

masterItems.length

Result: 1

masterItems.everyItem()

Result: [object PageItem]

// Note there is NO plural s this time!

masterItems.everyItem().constructor.name

Result: PageItem

// Note there is NO plural s this time!

masterItems.everyItem().getElements()

Result: [object TextFrame]

masterItems.everyItem().getElements().constructor.name

Result: Array

masterItems.everyItem().getElements().length

Result: 1

masterItems.everyItem().getElements()[0].itemLayer.name

Result: Draft

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

Thanks Laubender​.

So, it seems that everyItem() when used with pageItems returns a single object, no matter how many page items are in the collection:

  • .pageItems.length returns 3 (number in the collection)
  • .pageItems.everyItem() returns one pageItem object.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

Uwe, there is even more to it.

While masterItems claims to be an [object PageItems], it actually targets a multitude of collections - the three of them that contribute to the array of three lengths. To me this is a distinctive type by its behaviour. This works along the same principle as when you access one property via the everyItem() of a collection - that also yields an array of the property values, one per individually targeted object.

You also have to consider that ExtendScript will outsmart you on the result for some special cases of a single target, it will deliver the actual value rather than its array wrapper. This is especially annoying with xmlElements.itemByName() - you expect a single element and it works most of the time, but yields an array in case of accidental extra elements with the same tag.

You actually benefit from a similar simplification when getElements() in your example returns the single array. It could have yielded an array of 3 arrays, one containing your actual text frame and the others empty.

For comparison, have a look at this one:

app.activeDocument.masterSpreads.everyItem().pageItems.itemByRange(0,1).contents.toSource()

Ergebnis: ["a", "A", "b", "B", "c", "C"]

Three master spreads, two text frames each - or is it a different combination? You could not tell from the result when you were using everyItem() instead of itemByRange().

If you have a language with strict type checking such as Java, this way you will end up with four roughly similar classes, that just differentiate by array-ness of target and result.

app.activeDocument.masterSpreads.everyItem().pageItems.item(0).contents.toSource()

Ergebnis: ["a", "b", "c"]

The 3 collections iterated, item(0) of each then contributes to the contents array.

Now think about the class specific properties object returned by the ".properties" property. Another related type, it just omits the methods. It would be interesting to see how the language bindings for C# and others deal with the mentioned cases, it took me several weekends to sort this out for Java.

Dirk

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 22, 2017 Feb 22, 2017

Copy link to clipboard

Copied

LATEST

Wow, great and deep explanation!

> (…) To me this is a distinctive type by its behaviour (…)

I finally come to the same conclusion thanks to Uwe's tests and Dirk's interpretation. So there is a sneaky mistake in my previous message—which unfortunately I can no longer edit. It is not true that  xyz.collection.count()===xyz.collection.length  with all possible xyz specifiers.

Indeed, given

  • xyz a plural specifier in the …everyItem() form

and

  • collection a property (typically, pageItems) exposed in xyz actual type,

Uwe have discovered that xyz.collection.count() is an Array of numbers [z0, z1, …, zk], while xyz.collection.length is a single number N, such as N = Σ zk.

In our specific discussion we are talking about the entity myDoc.masterSpreads.everyItem().pageItems, whose type is the PageItems collection. Applying .length to it returns the total number of underlying page items, while applying .count() returns an array that still discriminates the count of page items for each masterspread.

var doc = app.activeDocument,

    entity = doc.masterSpreads.everyItem().pageItems;

alert( entity.toSource() );  // resolve("/document[@id=1]/master-spread/page-item")

alert( entity.count() );     // [z0,z1...]

alert( entity.length );      // Σ(zk)

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines