Copy link to clipboard
Copied
For example:
I want sel[j] to be positioned above sel[j-1];
var doc = app.activeDocument;
var item = doc.selection;
sel = items;
for (var i = 0; i < sel.length; i++) {
};
Do you want to move a page item up in the containing layer’s stacking order?
Here there are 3 page items in Layer 1 (there’s only 1 Document Layer). To move the selected item up 1 place in Layer 1’s stacking order (there is also s.bringToFront(), s.sendToBack(), s.sendBackward()):
var s = app.activeDocument.selection[0]
s.bringForward()
Hi @dublove this function can set the stacking order. I am using a left-then-top sorting function, but you can use any criteria for sorting.
- Mark
/**
* @file Set Item Stacking Order.js
* @author m1b
* @version 2025-10-25
*/
function main() {
var doc = app.activeDocument;
var items = doc.selection;
// must update `items` with new item references
items = setItemStackingOrder(doc, items, sortByLeftTop);
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoMode...
how do I use it?
var d = app.activeDocument
//a selection on the bottom layer
var s = d.selection[0]
//this doesn’t do anything because s
//is the only object on the item Layer named "Gray"
s.bringForward()
//make a new layer
var ns = makeLayer(d, "New Gray Layer");
//moves the selected page item to New Gray Layer
// note that the parameter has to be a reference to an item Layer
s.move(ns)
/**
* Makes a new named Layer
* @ param the document to add the layer
* @ param layer name
* Copy link to clipboard
Copied
Do you want to move a page item up in the containing layer’s stacking order?
Here there are 3 page items in Layer 1 (there’s only 1 Document Layer). To move the selected item up 1 place in Layer 1’s stacking order (there is also s.bringToFront(), s.sendToBack(), s.sendBackward()):
var s = app.activeDocument.selection[0]
s.bringForward()
Copy link to clipboard
Copied
Thanks, that's exactly what I meant.
Successfully completed.
There's no such thing as "bringToBottom"?
(Place it on the bottom layer)
Copy link to clipboard
Copied
Something seems off.
Is sort incorrect? Or is bringToFront() not working right?
The expected result should be 4 > 3 > 2 > 1.
But it appears to be jumbled.
var doc = app.activeDocument;
var items = doc.selection;
sel = items;
if (sel.length > 1) {
sortObj(sel);
}
for (var i = 0; i < sel.length; i++) {
bt(sel[i])
alert(sel[i]);
};
function bt(s) {
s.bringForward()
}
function sortObj(s) {
s.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];
}
});
}Copy link to clipboard
Copied
Hi @dublove this function can set the stacking order. I am using a left-then-top sorting function, but you can use any criteria for sorting.
- Mark
/**
* @file Set Item Stacking Order.js
* @author m1b
* @version 2025-10-25
*/
function main() {
var doc = app.activeDocument;
var items = doc.selection;
// must update `items` with new item references
items = setItemStackingOrder(doc, items, sortByLeftTop);
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Do Script');
/**
* Sets the stacking order of the given `items`,
* with optional `sorter` function and `parent`.
*
* Notes:
* - If no `sorter` is given, will keep the order
* of the `items` array.
* - If no `parent` is specified, will assign the
* parent of the first item.
*
* @author m1b
* @version 2025-10-25
* @param {Document} doc - an Indesign document.
* @param {Array<PageItem>} items - the page items to order.
* @param {Function} [sorter] - a sort function (default: use order of `items` array).
* @param {Spread|Group|Rectangle} [parent] - the `parent` of the items (note: items will be moved if necessary to ensure this parent).
*/
function setItemStackingOrder(doc, items, sorter, parent, reverse) {
var sortedItems = [];
for (var i = 0; i < items.length; i++)
sortedItems.push(items[i]);
if ('function' === typeof sorter)
sortedItems.sort(sorter);
var firstItem;
// collect the IDs
// we need IDs because changing the parents
// will likely mess up the references
var ids = [];
for (var i = 0; i < sortedItems.length; i++)
ids.push(sortedItems[i].id);
if (!parent)
parent = doc.pageItems.itemByID(ids[0]).parent;
if (reverse)
ids.reverse();
// move all to the same parent
// and set the stacking order
for (var i = sortedItems.length - 1, item; i > 0; i--) {
item = doc.pageItems.itemByID(ids[i]);
// must have the same parent
if (item.parent !== parent)
item.move(parent);
item = doc.pageItems.itemByID(ids[i]);
firstItem = doc.pageItems.itemByID(ids[0]);
// move behind the first item
item.sendToBack(firstItem);
}
return sortedItems;
};
/** Sort page item by left, then top, position. */
function sortByLeftTop(a, b) {
// if the items are as closer than this (points) then treat them as exactly lining up
const THRESHOLD = 2;
if (Math.abs(b.geometricBounds[1] - a.geometricBounds[1]) < THRESHOLD)
// x position is below threshold, so evaluate y position
return a.geometricBounds[0] - b.geometricBounds[0]
else if (a.geometricBounds[1] < b.geometricBounds[1])
return -1;
else if (a.geometricBounds[1] > b.geometricBounds[1])
return 1;
};
Edit 2025-10-25: fixed bug in sortByLeftTop where it sorted verticall the wrong direction.
Edit 2025-10-25: improved sortByLeftTop so that if items are *close* but not exactly aligned on X it will sort by Y.
Edit 2025-10-25: fixed another bug in sortByTopLeft!
Copy link to clipboard
Copied
Thanks, @m1b .
This is yet another entirely new way of thinking that I'm currently studying and researching.
I want to make 1 < 2 < 3 < 4.
Seems to have worked.
I changed this part: item.bringToFront(firstItem);
Copy link to clipboard
Copied
@dublove > I want to make 1 < 2 < 3 < 4.
That statement doesn't explain *how* you want to achieve that ordering.
My example orders them that way by using the X coordinate of the left edge of the item. But you could also sort them by their contents, and it would give the same ordering, in your sample document.
/** Sort page item by contents. */
function sortByContents(a, b) {
if (a.contents.toLowerCase() < b.contents.toLowerCase())
return -1;
else if (a.contents.toLowerCase() > b.contents.toLowerCase())
return 1;
else
// same contents
return 0;
};
Copy link to clipboard
Copied
Sorroy. I didn't describe it clearly.
First sort the elements by their left edges.
After sorting, stack them.
According to the diagram I've provided, Figure 1 should correspond to sel[0], but it appears the final selection has shifted to Figure 2.
Copy link to clipboard
Copied
The stacking hierarchy should be fine, but the sorting doesn't seem to match up.
Copy link to clipboard
Copied
> According to the diagram I've provided, Figure 1 should correspond to sel[0], but it appears the final selection has shifted to Figure 2.
You must update your variable `sel` with the new references. Like this:
var doc = app.activeDocument;
var sel = doc.selection;
// must update `sel` with new item references
sel = setItemStackingOrder(doc, self, sortByLeftTop);
// now sel[0] = "1", sel[1] = "2", etc
Copy link to clipboard
Copied
This seems to be correct.
I used the previous sorting method again.
setItemStackingOrder(sortByLeftTop, doc, sel);
sortObj(sel);
function sortObj(sel) {
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];
}
});
}
Copy link to clipboard
Copied
Oops, yes I put the "a" and "b" in the wrong order and didn't test it. Bug fixed now.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Thanks for the demo document. Again, I got the "a" and "b" around the wrong way and didn't test properly. I will update code above. - Mark
Copy link to clipboard
Copied
After running the script twice,
the correct result will be obtained.
If there are more images like this, you may need to run it more times.
Copy link to clipboard
Copied
@dublove when I run my script on your "script twice.indd", it works in one go. Your screenshot shows incorrect ordering anyway—the image that should be first becomes second. Have you updated to the latest version of the function? It works correctly for me.
Copy link to clipboard
Copied
Hi @m1b , sorry
This time seems to be correct.
I didn't notice you changed the very first line:
items = setItemStackingOrder(doc, items, sortByLeftTop);
Thank you very much.
Copy link to clipboard
Copied
@m1b It now appears unrelated to s[1]. Whoever was at the top of the stack before sorting will remain at the top after sorting.
I used item.bringToFront(firstItem);
But that probably isn't the crucial part.
It doesn't matter now though—it works well enough as is, and that detail isn't important.
I just need them sorted so I can see which images are present.
Copy link to clipboard
Copied
@dublove have a look at my new script above. The `sortByLeftTop` function works better now—if items are *almost* aligned by not exactly, the function will judge them by Y axis position.
Copy link to clipboard
Copied
Hi @m1b
Thank you very much.
Sorry, I just said it worked.
But when I tried again, it still failed.
When sel[1] is the same, taking sel[0] now still not works.
Copy link to clipboard
Copied
One thing to note is the sendTo and bringTo functions would not work if the objects are on different layers. Are you assuming the user does not use multiple item Layers?
To move between Layers you have to use the move() function. This doesn’t move anything if the objects are on different Layers
var s = app.activeDocument.selection[0]
s.bringForward()
alert("Selection is on " + s.itemLayer.name + " Layer")
Copy link to clipboard
Copied
Hi rob day.
move()?
For example,
how do I use it? If possible, I'd like to get it done in one go.
Copy link to clipboard
Copied
how do I use it?
var d = app.activeDocument
//a selection on the bottom layer
var s = d.selection[0]
//this doesn’t do anything because s
//is the only object on the item Layer named "Gray"
s.bringForward()
//make a new layer
var ns = makeLayer(d, "New Gray Layer");
//moves the selected page item to New Gray Layer
// note that the parameter has to be a reference to an item Layer
s.move(ns)
/**
* Makes a new named Layer
* @ param the document to add the layer
* @ param layer name
* @ return the new layer
*/
function makeLayer(d, n){
if (d.layers.itemByName(n).isValid) {
return d.layers.itemByName(n);
} else {
return d.layers.add({name:n});
}
}
Copy link to clipboard
Copied
Thank you.
This may require first determining whether all sel[j] are on the same layer. Only if they are not should s.move(ns) be executed.
Copy link to clipboard
Copied
It could quickly get complicated—move() only works if you are moving page items between item Layers, and places the item at the top of the target Layer. To move page items within a item Layer, you have to use .bringForward etc.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now