Skip to main content
dublove
Legend
Aug 11, 2026 11:49 AM UTC
Answered

How to modify the following code to obtain a non text box object?

Hello everyone.

I always select 2 objects.

One of the objects must be a text box.
The other object is a non text box object.

(Note: Another object is also an image, but when the image is pasted inside the frame, I cannot access it.)

Originally, a function of m1b could be specifically used to obtain image frames. But it is invalid for the exceptions mentioned above.


So I came up with two solutions: non text objects and text boxes.
Now I don't know how to modify the code below to obtain non text boxes.

There are attachments.
 

notTextFrames = getThingsWithFilter(items, function (item) { return item.hasOwnProperty('texts') && item.texts.length == 0 }, true);

The current issue is that I don't know how to modify the code for notTextFrames.

How to express the antonym of “hasOwnProperty”?

Complete code:

var doc = app.activeDocument,
items = doc.selection,

//graphicFrames = getThingsWithFilter(items, function (item) { return item.hasOwnProperty('graphics') && item.graphics.length > 0 }, false);

textFrame = getThingsWithFilter(items, function (item) { return item.hasOwnProperty('texts') && item.texts.length > 0 }, true);

notTextFrames = getThingsWithFilter(items, function (item) { return item.hasOwnProperty('texts') && item.texts.length == 0 }, true);

alert(notTextFrames.length);;

/**
* Returns any things which pass the `filter` function.
* @author m1b
* @version 2025-04-23
* @param {Array<*>} things - the things to search.
* @param {Function} filter - a function that, given a thing, returns true when it matches.
* @param {Boolean} [returnFirstThing] - whether to return the first thing only (default: false).
* @returns {Array<*>}
*/
function getThingsWithFilter(things, filter, returnFirstThing) {
var found = [];
for (var i = 0; i < things.length; i++) {
if (
'Group' === things[i].constructor.name
&& things[i].pageItems.length > 0
) {
var moreThings = getThingsWithFilter(things[i].pageItems.everyItem().getElements(), filter, returnFirstThing);
if (
returnFirstThing
&& undefined != moreThings
&& 'Array' !== moreThings.constructor.name
)
return moreThings;
if (moreThings.length > 0)
found = found.concat(moreThings);
continue;
}
if (!filter(things[i]))
continue;
if (returnFirstThing)
return things[i];
found.push(things[i]);
}
if (
returnFirstThing
&& 0 === found.length
)
return;
return found;
};

 

    rob day
    rob dayCorrect answer
    Community Expert
    Aug 12, 2026 7:59 PM UTC

    I wanted to simplify it with 'while', but it got stuck in a dead loop.

     

    So assuming the nested containers are rectangles, nothing is grouped, and all sorts of other problems associated with selections—this selects the outer containers:

     

    var sel = app.activeDocument.selection;
    var c;
    for (var i = 0; i < sel.length; i++){
    //get the selection’s outer container
    c = selectContainer(sel[i])
    app.select(c, SelectionOptions.ADD_TO)
    };

    /**
    * Selects the outer container of a selected rectangle
    * @ param the selection
    * @ return the selection’s outer container
    */
    function selectContainer(s){
    var p = s.parent
    if (p.constructor.name == "Spread") {
    return s
    } else {
    if (p.constructor.name == "Rectangle") {
    while (p.parent.constructor.name == "Rectangle") {
    p = p.parent
    }
    }
    }
    app.select(p)
    return p
    }

     

     

     

    8 replies

    rob day
    Community Expert
    Community Expert
    Aug 11, 2026 6:13 PM UTC

    Not sure what the function is doing, but it mostly throws errors for me. Also in your example the image on the right is in a rectangle that is nested inside of another rectangle. So:

     

    var s = app.activeDocument.selection
    alert("Selection is a "+ s[0].constructor.name + " Containing " + s[0].images.length + " Image")

     

     

    The left container contains 1 image:

     

    While the right container contains 0 images

     

     

     

     

    Translate
    dublove
    dubloveAuthor
    Legend
    Aug 12, 2026 4:36 AM UTC

    ​@rob day 

    The function is to obtain a framework containing images.
    This image uses' Paste inside ', which cannot be recognized by this function.

    I solved the problem of text boxes and non text box objects using “item.constructor.name == 'TextFrame’ ”.
    But I found that I still need to get the image of the "outermost frame" and "innermost image"

    Perhaps ​@m1b  can better understand his own logic.

     

    Translate
    dublove
    dubloveAuthor
    Legend
    Aug 11, 2026 4:38 PM UTC

    Of course,The most ideal scenario is make "graphicFrames" include the “ images in frames”  special case.

    Translate
    dublove
    dubloveAuthor
    Legend
    Aug 12, 2026 2:56 PM UTC

    When pasted internally, there are usually two "rectangles".

    I can make this judgment now, but I think it's not easy enough or scientific enough.
    If we could directly obtain the outermost layer, it would save us trouble.

    var doc = app.activeDocument;
    var item = doc.selection[0];
    items = doc.selection;
    //alert(item.graphics.length);

    var gra = getGraphics(items)
    alert(gra[0].constructor.name == "Image" && gra[0].parent.constructor.name == 'Rectangle' && gra[0].parent.parent.constructor.name == 'Rectangle');
    exit();

    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;
    };

     

    Translate