## Welcome to the Community!

We have a brand new look! Take a tour with us and explore the latest updates on Adobe Support Community.

• [SCRIPT] How to select most top/left object

# [SCRIPT] How to select most top/left object

Enthusiast ,
Jun 15, 2021 Jun 15, 2021

Copied

Hello gurus,

I need to select the most top/left object in a page.

The Y is the tiebreaker. Any suggestion?

I tried sorting by geometricBounds[0] and geometricBounds[1] but can not accomplish what I need.

TOPICS
Scripting

Views

266

Likes

Report

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

Enthusiast , Jun 15, 2021 Jun 15, 2021
I have no idea why, but I got it.Tired of playing with this sort function, I put this absurd and it works.If anyone understand the logic behind this function, I'd love to know. var doc = app.activeDocument; var pg = app.activeWindow.activePage; getFirstImg(pg); function getFirstImg(pg) { var gbs = []; for (var i=0; i<pg.rectangles.length; i++) { if (pg.rectangles[i].itemLayer == img && pg.rectangles[i].graphics.length) { var recgb = pg.rectangles[i].geometricBounds; gbs.push([recgb[0]...

Likes

Adobe Community Professional , Aug 10, 2021 Aug 10, 2021
For anyone wondering, here's the solution I came up with for Luis on a Facebook thread. The yThresh accounted for objects not perfectly aligned on the top (in mm), but could be set  to whatever threshold you felt appropriate.  var apis = app.activeDocument.pages[0].pageItems.everyItem().getElements(); apis.sort(function (a,b) { var agb = a.geometricBounds; var bgb = b.geometricBounds; var yThresh = Math.abs(agb[0] - bgb[0]); if (yThresh > 5) { if (agb[0] > bgb[0]) return 1; else if (bgb[0] > ...

Likes

6 Replies 6
Enthusiast ,
Jun 15, 2021 Jun 15, 2021

Copied

I have no idea why, but I got it.

Tired of playing with this sort function, I put this absurd and it works.

If anyone understand the logic behind this function, I'd love to know.

``````var doc = app.activeDocument;
var pg = app.activeWindow.activePage;
getFirstImg(pg);

function getFirstImg(pg) {
var gbs = [];
for (var i=0; i<pg.rectangles.length; i++) {
if (pg.rectangles[i].itemLayer == img && pg.rectangles[i].graphics.length) {
var recgb = pg.rectangles[i].geometricBounds;
gbs.push([recgb[0] , recgb[1] , pg.rectangles[i].graphics[0].itemLink.name , pg.rectangles[i]]);
}
}
gbs.sort(function(a, b) { return (a[0] - b[0]) + (a[1] - b[1]); });
app.select(gbs[0][3]);
}``````

Likes

Report

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

Copied

You create an array of subarrays, sort the array by top and left coordinates, then take the first item, which is gbs[0]. This array item is an array itself with the rectangle as the fourth element, which you address by gbs[0][3].

Likes

Report

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

Copied

In fact the elements are sorted by comparing their (top+left) sum. Just note that the sort key (a[0]–b[0])+(a[1]–b[1]) is nothing but (a[0]+a[1])–(b[0]+b[1]), that is, (top+left)₀ – (top+left)₁. This is on average a good approximation when the X and Y axes have the same priority. In the below example you can see that the winner is the rectangle that reaches the minimal sum (Σ=340.)

However, using the sort method for this purpose is clearly useless and expensive, since the minimum value can always be found in linear time O(N)—while sort relies on a loglinear algorithm, i.e. O(N×log(N)). I think you could just do as follows:

``````function selectFirstImage(/*?Layer|str*/ly,/*?Document*/doc,/*?Page*/pg,  t,a,b,c,i,iBest,xyMin)
//----------------------------------
// Select and return the (top+left)most image container on a page.
// `ly`   : Target layer or layer name (opt.)
// `doc`  : Target document (default=active.)
// `pg`   : Target page (default=active.)
// ---
// => SplineItems [OK]  |  false [KO]
{
// Checkpoint -> doc, pg
// ---
doc || (doc=app.properties.activeDocument||0);
if( !doc.isValid || 'Document' != doc.constructor.name ) return false;

pg || ((pg=app.properties.activeWindow)&&(pg=pg.properties.activePage)) || (pg=doc.pages[0]);
if( !pg.isValid || 'Page' != pg.constructor.name ) return false;

// Layer filter (optional.)
// ---
'string'==typeof ly && ly.length && (ly=doc.layers.itemByName(ly));
( ly && 'Layer'==ly.constructor.name && ly.isValid ) || (ly=void 0);

// Browse the SplineItems collection.
// ---
t = pg.splineItems.everyItem();
if( !t.isValid ) return false;
a = t.getElements();
b = ly ? t.itemLayer : [];

// Identify the object having the minimal (x+y) sum.
// ---
for
(
i=a.length, iBest=false, xyMin=1/0 ;
i-- ;
ly===b[i] && (t=a[i]).graphics.length && (t=t.geometricBounds)
&& xyMin > (t=t[0]+t[1]) && (xyMin=t, iBest=i)
);

return false !== iBest && (app.select(t=a[iBest]), t);
}

// Example:
selectFirstImage('Layer 1');``````

Likes

Report

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

Copied

Wow, thank you @Marc Autret!!!

Your knowledge makes em feel illiterate.

I tried your code in two different documents and nothing is being selected.

I just typed the layer name in the function call...

Likes

Report

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

Copied

Now I'm having the same difficult to select elements in row order.

Any help?

Likes

Report

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

Copied

LATEST

For anyone wondering, here's the solution I came up with for Luis on a Facebook thread. The yThresh accounted for objects not perfectly aligned on the top (in mm), but could be set  to whatever threshold you felt appropriate.

var apis = app.activeDocument.pages[0].pageItems.everyItem().getElements();
apis.sort(function (a,b) {
var agb = a.geometricBounds;
var bgb = b.geometricBounds;
var yThresh = Math.abs(agb[0] - bgb[0]);
if (yThresh > 5) {
if (agb[0] > bgb[0]) return 1;
else if (bgb[0] > agb[0]) return -1;
}
return agb[1] > bgb[1];
});

Likes

Report

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