Skip to main content
Legend
September 8, 2025
Answered

[ExtendScript] How to move layer children while preserving their order

  • September 8, 2025
  • 2 replies
  • 350 views

I'm writing code to move the contents of a layer to another layer. Moving pageItems alone works fine, but when sublayers and pageItems are at the same level, I don't know how to move them while preserving their order.

 

As far as I know, the only way is to retrieve pageItems and layers separately, which results in two clusters after moving—like beer liquid and foam. How to solve this problem?

(function() {
  if(app.documents.length <= 0) {return ;}
  var doc = app.documents[0] ;
  var srcLayer = doc.layers[1] ;
  var dstLayer = doc.layers[0] ;

  var pageItems = srcLayer.pageItems ;
  for(var i = pageItems.length - 1 ; i >= 0 ; i--) {
    pageItems[i].move(dstLayer, ElementPlacement.PLACEATEND) ;
  }
  var sublayers = srcLayer.layers ;
  for(var i = sublayers.length - 1 ; i >= 0 ; i--) {
    sublayers[i].move(dstLayer, ElementPlacement.PLACEATEND) ;
  }
})() ;

 

Update:
Added the test data (.ai) and before/after image.

 

Correct answer CarlosCanto

yes, as far as I know, we have to move pageItems and sublayers separately. I was going to mess with absoluteZorderPosition but I thought it would be easier to add an "anchor" right before (or after) each sublayer.

 

(function() {
  if(app.documents.length <= 0) {return ;}
  var doc = app.documents[0] ;
  var srcLayer = doc.layers[1] ;
  var dstLayer = doc.layers[0] ;

  // add dummy placeholders above each sublayer
  var dummyPlacehodlers = [];

  var sublayers = srcLayer.layers ;
  for(var i = sublayers.length - 1 ; i >= 0 ; i--) {
    dummyPlacehodlers[i] = srcLayer.pathItems.rectangle(0,0,1,1) ;
    dummyPlacehodlers[i].move(sublayers[i], ElementPlacement.PLACEBEFORE) ;
  }

  var pageItems = srcLayer.pageItems ;
  for(var i = pageItems.length - 1 ; i >= 0 ; i--) {
    pageItems[i].move(dstLayer, ElementPlacement.PLACEATEND) ;
  }

  var sublayers = srcLayer.layers ;
  for(var i = sublayers.length - 1 ; i >= 0 ; i--) {
    sublayers[i].move(dummyPlacehodlers[i], ElementPlacement.PLACEAFTER);
    dummyPlacehodlers[i].remove() ;
  }
})() ;

2 replies

CarlosCanto
Community Expert
CarlosCantoCommunity ExpertCorrect answer
Community Expert
September 8, 2025

yes, as far as I know, we have to move pageItems and sublayers separately. I was going to mess with absoluteZorderPosition but I thought it would be easier to add an "anchor" right before (or after) each sublayer.

 

(function() {
  if(app.documents.length <= 0) {return ;}
  var doc = app.documents[0] ;
  var srcLayer = doc.layers[1] ;
  var dstLayer = doc.layers[0] ;

  // add dummy placeholders above each sublayer
  var dummyPlacehodlers = [];

  var sublayers = srcLayer.layers ;
  for(var i = sublayers.length - 1 ; i >= 0 ; i--) {
    dummyPlacehodlers[i] = srcLayer.pathItems.rectangle(0,0,1,1) ;
    dummyPlacehodlers[i].move(sublayers[i], ElementPlacement.PLACEBEFORE) ;
  }

  var pageItems = srcLayer.pageItems ;
  for(var i = pageItems.length - 1 ; i >= 0 ; i--) {
    pageItems[i].move(dstLayer, ElementPlacement.PLACEATEND) ;
  }

  var sublayers = srcLayer.layers ;
  for(var i = sublayers.length - 1 ; i >= 0 ; i--) {
    sublayers[i].move(dummyPlacehodlers[i], ElementPlacement.PLACEAFTER);
    dummyPlacehodlers[i].remove() ;
  }
})() ;
CarlosCanto
Community Expert
Community Expert
September 8, 2025

the layering order is upside down for now, but that the way your original function is.

sttk3Author
Legend
September 8, 2025

Thanks, your method made it possible. Here's the code that changed the reverse order to the intended order.

(function() {
  if(app.documents.length <= 0) {return ;}
  var doc = app.documents[0] ;
  var srcLayer = doc.layers[1] ;
  var dstLayer = doc.layers[0] ;

  // add dummy placeholders above each sublayer
  var dummyPlacehodlers = [] ;

  var sublayers = srcLayer.layers ;
  var lastSublayerIndex = sublayers.length - 1 ;
  for(var i = lastSublayerIndex ; i >= 0 ; i--) {
    var dummyPlacehodler = srcLayer.groupItems.add() ;
    dummyPlacehodlers.unshift(dummyPlacehodler) ;
    dummyPlacehodler.move(sublayers[i], ElementPlacement.PLACEBEFORE) ;
  }

  var pageItems = srcLayer.pageItems ;
  for(var i = pageItems.length - 1 ; i >= 0 ; i--) {
    pageItems[i].move(dstLayer, ElementPlacement.PLACEATBEGINNING) ;
  }

  for(var i = lastSublayerIndex ; i >= 0 ; i--) {
    sublayers[i].move(dummyPlacehodlers[i], ElementPlacement.PLACEAFTER) ;
    dummyPlacehodlers[i].remove() ;
  }
})() ;

 

m1b
Community Expert
Community Expert
September 8, 2025

Hi @sttk3 can you please post a test case document showing how you'd like to control the layering? Before and after?

 

I know you are an expert, so I know this is going to be a challenge. I hope @CarlosCanto sees this!

- Mark

sttk3Author
Legend
September 8, 2025

Yes, I'll add the test data to the source question.