Beenden
  • Globale Community
    • Sprache:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티

I'm completely confused by "app.documents[0].selection"and "app.activeDocument.selection[0]"

Ratgeber ,
Sep 04, 2025 Sep 04, 2025
When I select a text box, both of the following are correct:
var sel = app.documents[0].selection;
alert(sel); // [object TextFrame]
alert(sel.length) // 1​


When my cursor is inside the text, I tried the code below and found both are [object TextFrame], but sel.length is invalid..
It should be noted that sel is undefined.

    item = app.activeDocument.selection[0];
    if (item.parent.textFrames[0].constructor.name == "TextFrame") {
        var sel = item.parent.textFrames[0];
    }
    alert(sel);//[object TextFrame]
    alert(sel.length)//undefined?????
THEMEN
Anleitungen , Skripterstellung
543
Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines

correct answers 2 richtige Antworten

Community Expert , Sep 04, 2025 Sep 04, 2025

@dublove yes definitely. That is the way I would code it. I had a quick search and I have already written a function (for you, back in 2022!). Here is an example usage:

/**
 * @author m1b
 */
function main() {

    var doc = app.activeDocument;
    var sel = getTextFrames(doc.selection);

    alert('sel = ' + sel + ' (length: ' + sel.length + ')');

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Test');

/**
 * Returns any text frames found in given `items`
...
Übersetzen
Community Expert , Sep 05, 2025 Sep 05, 2025

@dublove I wrote this function for getting the table. Not sure how good it is.

- Mark

 

function main() {

    var doc = app.activeDocument;
    var table = getTable(doc.selection);

    alert(table);

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Test');

/**
 * Attempts to return a Table, given an object.
 * @author m1b
 * @version 2023-02-06
 * @param {InsertionPoint|Text|Cells|Table|TextFrame} obj - an object related to a Cell.
 * @returns {Cell}
 */
f
...
Übersetzen
Community Expert ,
Sep 04, 2025 Sep 04, 2025

@dublove there's usually no difference between app.activeDocument and app.documents[0].

 

Your problem is simply that sometimes the line

var sel = item.parent.textFrames[0];

doesn't get called, due to the predicate, so it will throw an error.

 

If you want to handle the error gracefully, do it like this:

var item = app.activeDocument.selection[0];

// must define sel outside the if/else
var sel;

if (item.parent.textFrames[0].constructor.name == "TextFrame") {
    sel = item.parent.textFrames[0];
}
else {
    sel = { length: 0 };
}

alert(sel);
alert(sel.length);
Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 04, 2025 Sep 04, 2025

Hi m1b.

As you mentioned, is the value of sel.length 0?
But sel is already an object [object TextFrame].
If that's the case, my sort(a,b) interaction below won't capture the objects and will throw an error.

Actually, I just want to automatically obtain the final TextFrame based on different selections.

 alert(item.constructor.name);
    var sel;
    item = app.activeDocument.selection[0];
    if (item.parent.textFrames[0].constructor.name == "TextFrame") {
        sel = item.parent.textFrames[0];
    }
    else if (
        item.constructor.name == "Image"
        || item.constructor.name == "TextFrame") {
        sel = app.documents[0].selection;
    }
        sel.sort(function (a, b) {
        var aBounds = a.visibleBounds;
        var bBounds = b.visibleBounds;
 
        if (aBounds[1] < bBounds[1]) {
            return -1;
        } else if (aBounds[1] > bBounds[1]) {
            return 1;
        }
        else {
            return bBounds[0] - aBounds[0];
        }
    });
Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Neu hier ,
Sep 04, 2025 Sep 04, 2025

Really helpful breakdown — I’ve run into similar issues where features behave differently depending on device or context. It reminds me how important it is to double-check workflows across platforms, whether it’s Excel or even how a website displays on mobile vs desktop. Consistency really makes or breaks productivity.

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Community Expert ,
Sep 04, 2025 Sep 04, 2025

@m1b said: "there's usually no difference between app.activeDocument and app.documents[0]."

 

Hi @dublove ,

the difference between app.documents[0] and app.activeDocument is a subtle one.

It could be that the addressed document with app.documents[0] is a document without a layout window.

Not so with app.activeDocument. That is always one with a layout window.

 

Let's proof that; start InDesign with no document open and add two documents with a different parameter for showingWindow in method add():

// START InDesign WITH NO OPEN DOCUMENT:
// Add two documents:
var doc1 = app.documents.add(); // showingWindow parameter true is default
var doc2 = app.documents.add( false ); // showingWindow parameter set to false

alert( app.documents.length ) ; // returns 2

alert( app.activeDocument == doc1 ); // returns true

 

Regards,
Uwe Laubender
( Adobe Community Expert )

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 04, 2025 Sep 04, 2025

@Laubender 

Too deep.
Can't grasp it all at once.
How do I make `sel = item.parent.textFrames[0];` into a real, controllable object?

It should be controllable like `sel = app.documents[0].selection;`.

 

I tried using
alert(app.documents[0].selection.parent);
but app.documents[0].selection doesn't seem to support parent.

 

It seems like alert(app.documents[0].selection[0].parent.textFrames[0]);
But sel.app.documents[0].selection[0].parent.textFrames[0];
still cannot be recognized as a real textFrame.
It remains a fake (logical textFrame?)

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 04, 2025 Sep 04, 2025

Hi @m1b @Laubender 

In other words, the textFrame obtained through conversion is not a true selection object.
It is not a collection and does not have a length property.
Does it need to be converted into a collection?

sel = [item.parent.textFrames[0]];
 

This time sort(a,b) didn't trigger an alert.

But the subsequent alert(“A:” + sel[0].parentPage) is invalid.

 

@m1b Is it possible to have something similar to the image?
As long as the cursor is within the text box, always return the textFrame object.

 

    var doc = app.activeDocument,
        items = doc.selection;
var graphics = getGraphics(doc.selection);
function getGraphics(items) {
    var graphics = [];
    if ('Array' === items.constructor.name) {
        for (var i = 0; i < items.length; i++)
            graphics = graphics.concat(getGraphics(items[i]));
    }

    else if (
        items.hasOwnProperty('allGraphics')
        && items.allGraphics.length > 0
    )
        graphics = graphics.concat(items.allGraphics);
    else if (
        items.hasOwnProperty('allPageItems')
        && items.allPageItems.length > 0
    )
        graphics = graphics.concat(getGraphics(items.allGraphics));
    else if ('Image' === items.constructor.name) {
        graphics.push(items);
    }
    return graphics;
};

 

 

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Community Expert ,
Sep 04, 2025 Sep 04, 2025

@dublove yes definitely. That is the way I would code it. I had a quick search and I have already written a function (for you, back in 2022!). Here is an example usage:

/**
 * @author m1b
 */
function main() {

    var doc = app.activeDocument;
    var sel = getTextFrames(doc.selection);

    alert('sel = ' + sel + ' (length: ' + sel.length + ')');

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Test');

/**
 * Returns any text frames found in given `items`.
 * @author m1b
 * @version 2025-09-19
 * @param {Array<PageItem>} items - a DOM item or items to search in, eg. doc.selection.
 * @returns {Array<TextFrame>}
 */
function getTextFrames(items) {

    if (undefined == items)
        return [];

    var parentTextFrames = [];
    var found = [];
    var already = {};

    if (!items.hasOwnProperty('0'))
        items = [items];

    for (var i = 0, item; i < items.length; i++) {

        item = items[i];

        if (
            item.hasOwnProperty('pageItems')
            && item.pageItems.length > 0
        )
            found = found.concat(getTextFramesFromInside(item.pageItems.everyItem().getElements()));

        if (
            item.hasOwnProperty('parentTextFrames')
            && item.parentTextFrames.length > 0
        )
            // is contained by textFrame(s)
            found = found.concat(getTextFrames(item.parentTextFrames));

        if (item.hasOwnProperty('parentStory'))
            // is in a story, which may contain textFrames
            found = found.concat(getTextFrames([item.parentStory]));

        // has a parent which might be a textFrame
        if (item.hasOwnProperty('parent')) {

            while (
                item.hasOwnProperty('parent')
                && 'Document' !== item.constructor.name
            ) {

                if ('TextFrame' === item.constructor.name)
                    parentTextFrames.push(item);

                if (
                    item.hasOwnProperty('parentTextFrames')
                    && item.parentTextFrames.length > 0
                )
                    parentTextFrames = parentTextFrames.concat(item.parentTextFrames);

                item = item.parent;

            }

            if (parentTextFrames.length > 0)
                found = found.concat(parentTextFrames);

        }

    }

    // unique text frames only
    var uniqueFrames = [];

    for (var i = 0; i < found.length; i++) {
        if (!already[found[i].id]) {
            uniqueFrames.push(found[i]);
            already[found[i].id] = true;
        };
    }

    return uniqueFrames;

    /** Returns text frames from inside the `items` */
    function getTextFramesFromInside(items) {

        var found = [];

        if (!items.hasOwnProperty('0'))
            items = [items];

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

            var item = items[i];

            if (
                item.hasOwnProperty('pageItems')
                && item.pageItems.length > 0
            )
                found = found.concat(getTextFramesFromInside(item.pageItems.everyItem().getElements()));

            else if ('TextFrame' === item.constructor.name)
                found.push(item);

        }

        var textFrames = [];

        for (var i = 0; i < found.length; i++)
            if ('TextFrame' === found[i].constructor.name)
                textFrames.push(found[i]);

        return textFrames;

    };

};

Edit 2025-09-05: fixed bug in getTextFrames function that caused stack overrun.

Edit 2025-09-19: improvement to—hopefully!—get more text frames in more cases.

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 04, 2025 Sep 04, 2025

Hi m1b.

You're incredibly formidable, far ahead of your time.
Back in 2022, I didn't even have the capacity to recognize this issue existed.

 

 

This is perfect. The problem is solved in an instant.

Thank you very much.

 

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 04, 2025 Sep 04, 2025

Hi @m1b 

Is there a table version?
Whether you select text within a cell, select a cell, or select a table, it always returns "Table".
When the cursor is inside a table, I don't want to get textFrame.

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Community Expert ,
Sep 05, 2025 Sep 05, 2025

@dublove I wrote this function for getting the table. Not sure how good it is.

- Mark

 

function main() {

    var doc = app.activeDocument;
    var table = getTable(doc.selection);

    alert(table);

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Test');

/**
 * Attempts to return a Table, given an object.
 * @author m1b
 * @version 2023-02-06
 * @param {InsertionPoint|Text|Cells|Table|TextFrame} obj - an object related to a Cell.
 * @returns {Cell}
 */
function getTable(obj) {

    if (obj == undefined)
        return;

    if ('Array' === obj.constructor.name) {
        for (var i = 0, table; i < obj.length; i++) {
            table = getTable(obj[i]);
            if (table && table.isValid)
                return table;
        }
        return;
    }

    if (obj.constructor.name == 'Cell')
        return obj.parent;

    if (obj.parent.constructor.name == 'Cell')
        return obj.parent.parent;

    if (
        obj.hasOwnProperty('cells')
        && obj.cells.length > 0
    )
        return obj.cells[0].parent;

    if (
        obj.hasOwnProperty('tables')
        && 0 !== obj.tables.length
    )
        return obj.tables[0];

};
Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 05, 2025 Sep 05, 2025

@m1b 

There's an issue:

If I currently have an image selected,

getTextFrames(doc.selection) does not return null.    Instead, it incorrectly displays my entire script code.


getGraphics(doc.selection) does not seem to have this issue. Even if I select text, it returns null(Nothing unusual occurred.).

 

In other words, if getTextFrames() fails to retrieve results, it will throw an error.

 

var doc = app.activeDocument;
var items = doc.selection;
var grs = getGraphics(doc.selection);
var tfs = getTextFrames(doc.selection);

 

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Community Expert ,
Sep 05, 2025 Sep 05, 2025

Thanks @dublove, I have corrected the bug in my getTextFrames function.

- Mark

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 05, 2025 Sep 05, 2025

Hi m1b.

Thank you very much.

 

This morning I used `graphics.length > 0 for the check.
Now ,haver replaced TextFrames, no exceptions.

 

Can TextFrames be divided into two scenarios:
A: Cursor inside the table.
B: Cursor outside the table.

 

Because sometimes when the cursor is inside the table, I don't want the text box to be affected.
Alternatively, it can be distinguished like this:

if(getTextFrames && !table) {
}

 

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 05, 2025 Sep 05, 2025

Hi @m1b 

If a text box is selected, it contains two tables.
getTable(doc.selection); only returns one table.

Is it possible to restrict the return to all tables within the text box, or all tables in the Story?

 

Additionally, when the cursor is within a cell, `getTable(doc.selection)` is not a collection and does not have a length property.

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 07, 2025 Sep 07, 2025

Hi @m1b 

Found a minor bug:
When  cells are selected, 'getTextFrames' does not retrieve the textFrame.

0061.png

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 18, 2025 Sep 18, 2025

@m1b 

If I select an image within text, can I return a TextFrame?

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Community Expert ,
Sep 18, 2025 Sep 18, 2025

Hi @dublove ,

if you select an object, a graphic frame for example, that is anchored to text, you will get the anchor character with:

app.selection[0].parent

If you'd select the image inside the graphic frame, then do:

app.selection[0].parent.parent

The anchor character's first or second insertion point could be asked to reveal the text frame:

app.selection[0].parent.parent.insertionPoints[0].parentTextFrames[0]

 

Kind regards,
Uwe Laubender
( Adobe Community Expert )

 

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 18, 2025 Sep 18, 2025

Hi @Laubender 

I want to modify the getTextFrames method in @m1b.
But I don't understand it.

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Community Expert ,
Sep 18, 2025 Sep 18, 2025

> If I select an image within text, can I return a TextFrame?

 

Yes, here is an example:

(function () {

    var doc = app.activeDocument;
    var textFrame = getParentTextFrame(doc.selection[0]);

    alert(textFrame);

})();

/**
 * Returns a parent text frame, where possible,
 * given a page item.
 * @author m1b
 * @version 2025-09-19
 * @Param {PageItem} item - an Indesign page item.
 * @Returns {TextFrame?}
 */
function getParentTextFrame(item) {

    if (!item)
        return;

    while (item.hasOwnProperty('parent')) {

        if ('TextFrame' === item.constructor.name)
            return item;

        if (
            item.hasOwnProperty('parentTextFrames')
            && item.parentTextFrames.length > 0
        )
            return item.parentTextFrames[0];

        item = item.parent;

    }

};

 

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 18, 2025 Sep 18, 2025

Hi @m1b 

Should we create another one? Too many are hard to control.
Can we merge it into the function getTextFrames(items)?

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Community Expert ,
Sep 18, 2025 Sep 18, 2025

Oh I understand. I think it will work. I have hopefully improved the function above.

- Mark

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines
Ratgeber ,
Sep 18, 2025 Sep 18, 2025
AKTUELL

Thank you.
It's bound to get better and better.
When I have time, I'll have to take a closer look at how you pulled it off.

Übersetzen
Melden
Community-Richtlinien
Seien Sie freundlich und respektvoll, geben Sie die ursprüngliche Quelle der Inhalte an und suchen Sie vor dem Absenden Ihres Beitrags nach Duplikaten. Weitere Informationen
community guidelines