Copy link to clipboard
Copied
I am looking for a script that moves all individual items to their own layer using the same layer name.
Hi @nutradial, this is a quick one. - Mark
/**
* @file One Item Per Layer.js
*
* Moves all document's page items to a new top-level layer,
* matching properties of the item's original layer.
*
* @author m1b
* @version 2024-12-19
*/
(function () {
var doc = app.activeDocument,
items = doc.pageItems;
// loop over the page items, backwards,
// moving each to a new layer, which is
// a copy of the original layer
for (var i = items.length - 1, item, layer, newL
...
@nutradial this is one way...
/**
* @file One Item Per Layer 2.js
*
* Moves a layer's page items to a new top-level layer,
* matching properties of the item's original layer.
*
* @author m1b
* @version 2024-12-19
*/
(function () {
// will only target this layer
const TARGET_LAYER = 'Layer 2';
var doc = app.activeDocument,
items = doc.pageItems;
// loop over the page items, backwards,
// moving each to a new layer, which is
// a copy of the original laye
...
Copy link to clipboard
Copied
Hi @nutradial, this is a quick one. - Mark
/**
* @file One Item Per Layer.js
*
* Moves all document's page items to a new top-level layer,
* matching properties of the item's original layer.
*
* @author m1b
* @version 2024-12-19
*/
(function () {
var doc = app.activeDocument,
items = doc.pageItems;
// loop over the page items, backwards,
// moving each to a new layer, which is
// a copy of the original layer
for (var i = items.length - 1, item, layer, newLayer; i >= 0; i--) {
item = items[i];
layer = getLayer(item);
if (!layer)
continue;
layer.locked = false;
layer.visible = true;
// create the new layer
newLayer = doc.layers.add();
newLayer.color = layer.color
newLayer.locked = layer.locked
newLayer.name = layer.name
newLayer.preview = layer.preview
newLayer.printable = layer.printable
newLayer.visible = layer.visible
// move into place
newLayer.move(layer, ElementPlacement.PLACEAFTER);
item.move(newLayer, ElementPlacement.PLACEATBEGINNING);
}
// remove empty layers
for (var i = doc.layers.length - 1; i >= 0; i--)
if (0 === doc.layers[i].pageItems.length)
doc.layers[i].remove();
/**
* Returns an item's layer.
* @param {PageItem} item - an Illustrator PageItem.
* @returns {Layer?}
*/
function getLayer(item) {
var layer = item.parent;
while (
undefined !== layer
&& layer.hasOwnProperty('parent')
&& 'Document' !== layer.parent.constructor.name
)
layer = layer.parent;
if ('Layer' === layer.constructor.name)
return layer;
};
})();
Copy link to clipboard
Copied
What needs to change to have the "One Item Per Layer.js" script only affect a specific layer (i.e. Layer 2)?
Copy link to clipboard
Copied
@nutradial this is one way...
/**
* @file One Item Per Layer 2.js
*
* Moves a layer's page items to a new top-level layer,
* matching properties of the item's original layer.
*
* @author m1b
* @version 2024-12-19
*/
(function () {
// will only target this layer
const TARGET_LAYER = 'Layer 2';
var doc = app.activeDocument,
items = doc.pageItems;
// loop over the page items, backwards,
// moving each to a new layer, which is
// a copy of the original layer
for (var i = items.length - 1, item, layer, newLayer; i >= 0; i--) {
item = items[i];
layer = getLayer(item);
if (
!layer
|| TARGET_LAYER !== layer.name
)
continue;
layer.locked = false;
layer.visible = true;
// create the new layer
newLayer = doc.layers.add();
newLayer.color = layer.color
newLayer.locked = layer.locked
newLayer.name = layer.name
newLayer.preview = layer.preview
newLayer.printable = layer.printable
newLayer.visible = layer.visible
// move into place
newLayer.move(layer, ElementPlacement.PLACEAFTER);
item.move(newLayer, ElementPlacement.PLACEATBEGINNING);
}
// remove empty layers
for (var i = doc.layers.length - 1; i >= 0; i--) {
if (
TARGET_LAYER === doc.layers[i].name
&& 0 === doc.layers[i].pageItems.length
)
doc.layers[i].remove();
}
/**
* Returns an item's layer.
* @param {PageItem} item - an Illustrator PageItem.
* @returns {Layer?}
*/
function getLayer(item) {
var layer = item.parent;
while (
undefined !== layer
&& layer.hasOwnProperty('parent')
&& 'Document' !== layer.parent.constructor.name
)
layer = layer.parent;
if ('Layer' === layer.constructor.name)
return layer;
};
})();
Copy link to clipboard
Copied
To bring it all home and finish the lesson ... how about within a sublayer.
Copy link to clipboard
Copied
Again, there are so many ways, but here is one approach. I wanted to do it differently to the first script to make it more flexible. This time you can specify a targetLayerName (or names if you use an array, or none to apply to all layers). Like this:
/**
* @File One Item Per Layer 3.js
*
* Moves each of a layer's page items to a new top-level layer,
* matching properties of the item's original layer.
*
* @author m1b
* @version 2024-12-21
* @discussion https://community.adobe.com/t5/illustrator-discussions/script-to-arrange-one-pathitem-per-layer/m-p/15047388
*/
(function () {
var settings = {
/**
* The layer(s) to target
* - if String, target that single layer
* - if Array, target multiple layers
* - if undefined, target all layers
*/
targetLayerName: ['Sublayer 2.1', 'Sublayer 2.1.1'],
};
if (0 === app.documents)
return alert('Please open a document and try again.');
if (
undefined != settings.targetName
&& 'Array' !== settings.targetName.constructor.name
)
settings.targetName = [settings.targetName];
var doc = app.activeDocument,
items = doc.pageItems,
moves = [],
removeMe = new Unique();
itemLoop:
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (!item.hasOwnProperty('parent'))
continue;
var obj = item,
topLayer = undefined,
parentLayer = undefined;
while (!topLayer) {
obj = obj.parent;
if (!obj.hasOwnProperty('parent'))
continue itemLoop;
if (
'Layer' === obj.constructor.name
&& !parentLayer
)
parentLayer = obj;
if ('Document' === obj.parent.constructor.name)
topLayer = obj;
}
if ('Layer' !== topLayer.constructor.name)
continue itemLoop;
if (settings.targetLayerName) {
if (indexOf(parentLayer.name, settings.targetLayerName) !== -1)
// match this layer by name
removeMe.push(parentLayer);
else
continue itemLoop;
}
else
removeMe.push(topLayer);
// remove the layer once empty
removeMe.push(topLayer);
moves.push({
item: items[i],
layer: topLayer,
layerName: parentLayer.name,
});
}
// perform the moves
for (var i = moves.length - 1; i >= 0; i--) {
var move = moves[i],
newLayer;
move.layer.locked = false;
move.layer.visible = true;
// create the new layer
newLayer = doc.layers.add();
newLayer.color = move.layer.color;
newLayer.locked = move.layer.locked;
newLayer.name = move.layerName;
newLayer.preview = move.layer.preview;
newLayer.printable = move.layer.printable;
newLayer.visible = move.layer.visible;
// move into place
newLayer.move(move.layer, ElementPlacement.PLACEAFTER);
move.item.move(newLayer, ElementPlacement.PLACEATBEGINNING);
}
// remove empty layers
for (var i = removeMe.length - 1; i >= 0; i--)
if (isEmpty(removeMe[i]))
removeMe[i].remove();
})();
/**
* An array-like object that won't contain duplicates.
* @author m1b
* @version 2024-12-21
*/
function Unique() {
this.array = [];
this.length = 0;
this.push = function pushUnique(obj) {
for (var i = 0; i < this.array.length; i++)
if (this.array[i] === obj)
return;
this.array.push(obj);
this.length++;
this[this.length - 1] = obj;
};
this.toString = function uniqueToString() {
return String(this.array);
};
};
/**
* Returns index of obj in arr.
* Returns -1 if not found.
* @Param {any} obj
* @Param {Array} arr
* @Returns {Number}
*/
function indexOf(obj, arr) {
for (var i = 0; i < arr.length; i++)
if (arr[i] === obj)
return i;
return -1;
};
/**
* Returns true when the layer and its sublayers are all empty.
* @Param {Layer} layer - an Illsutrator Layer.
* @Returns {Boolean}
*/
function isEmpty(layer) {
if (!layer)
return false;
if (layer.layers.length > 0) {
for (var i = 0; i < layer.layers.length; i++) {
if (!isEmpty(layer.layers[i]))
return false;
}
}
if (layer.pageItems.length > 0)
return false;
return true;
};
Copy link to clipboard
Copied
@m1b Nice update. I like how it splits up compoundPathItems and groupItems into new individual top-level layers. It does create an empty top-level layer when it does this which is not a big deal. Thanks again, I'm learinng a lot from your posts.