Auto-arrange per Y value (position)

Community Beginner ,
Aug 03, 2018 Aug 03, 2018

Copy link to clipboard

Copied

Hi! I have a question:

I wonder if there's a way to select a group of objects (in the same layer) and auto-arrange them based on each object's Y value (vertical position on the page).

This would be helpful in creating basic perspectives.

Perhaps a script?

Thanks!

TOPICS
Scripting

Views

1.6K

Likes

Translate

Translate

Report

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

correct answers 1 Correct Answer

Adobe Community Professional , Aug 03, 2018 Aug 03, 2018
not the prettiest thing int he world, but it does the trick. give this a shot:function test(){    if(!app.documents.length)    {        alert("You must have a document open.");        return;    }    var docRef = app.activeDocument;    var sel = docRef.selection;    if(!sel.length)    {        alert("You must make a selection.");        return;    }    function sortVertically(items)    {        var topMost,curY,delIndex,curItem,tempItems = [];        for(var x=0,len=items.length;x<len;x++)      ...

Likes

Translate

Translate
Adobe Community Professional ,
Aug 03, 2018 Aug 03, 2018

Copy link to clipboard

Copied

not the prettiest thing int he world, but it does the trick. give this a shot:

function test()

{

    if(!app.documents.length)

    {

        alert("You must have a document open.");

        return;

    }

    var docRef = app.activeDocument;

    var sel = docRef.selection;

    if(!sel.length)

    {

        alert("You must make a selection.");

        return;

    }

    function sortVertically(items)

    {

        var topMost,curY,delIndex,curItem,tempItems = [];

        for(var x=0,len=items.length;x<len;x++)

        {

            tempItems.push(items);

        }

        while(tempItems.length)

        {

            topMost = tempItems[0];

            curY = topMost.top;

            delIndex = 0;

            for(var x=1, len = tempItems.length;x<len;x++)

            {

                curItem = tempItems;

                if(curItem.top > curY)

                {

                    topMost = curItem;

                    curY = curItem.top;

                    delIndex = x;

                }

            }

            topMost.zOrder(ZOrderMethod.BRINGTOFRONT);

            tempItems.splice(delIndex,1);

        }

    }

    sortVertically(sel);

   

}

test();

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Thank you very, very much!

Worked like a charm!

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Salut !

Je me permet de proposer une autre façon plus souple.

I allow myself to propose another more flexible way.

// JavaScript Document

function test() {

    if (!selection.length) return;

    var reverse = false;

    var sel = selection;

      function sortVertically(items,zd) {

        var tab = [];

          for(var n = 0; n < items.length; n++) {

            tab = [];

            tab[0]= items.top;

            tab[1]= items;

          }

        tab.sort();

          if (zd) tab.reverse();

          for (n = 0; n < sel.length; n++) {

            tab[1].zOrder(ZOrderMethod.BRINGTOFRONT);

          }

      }

    sortVertically(sel,reverse);

}

if (app.documents.length) {test();}

de LR

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 05, 2020 Sep 05, 2020

Copy link to clipboard

Copied

I need to reorder objects by y position and it looks like this script will do exactly what I need, but I get an error when I try to run it...

Screen Shot 2020-09-05 at 4.46.42 PM.png

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Can you help me? I need to order objects by the row (if possible I need to round y position of objects (to group them to row) for some value that I can enter in a script manually) from right down corner of airboard and each row sort by decreasing x position.

Bars 1_cut.jpg

From top to down order in the layer should be 1,2,3,4,5,6 and etc.

thanks in advance

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Dec 08, 2018 Dec 08, 2018

Copy link to clipboard

Copied

I'm not sure i follow exactly what you mean. you just want to take any items that exist at the same Y position (plus or minus some buffer) and group them together, then take the resulting groups and sort them in descending order from top to bottom?

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

For example

autosave_CUT.jpg

I want to sort this objects from bottom to top by rounded Y for simplify sorting process. Rounding will create virtual rows highest value goes first (Top in the layers list). Then each row I want to sort by X, from right to the left (so high value goes first - revers order)

This is like sorting 2 dimensional array in revers order:

X,Y array

myobjlist= [[124,2],[23,2],[60,1],[150,1],[12,2],[20,0],[50,1],[40,0],[70,0]]

sorted(myobjlist)

will create next array
[[124, 2] [23, 2] [12, 2] [150, 1] [60, 1] [50, 1] [70, 0] [40, 0] [20, 0]]

Object with [124, 2] coordinates will be first in layers list and [20, 0] - last

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Salut,

Une approche si cela peut aider (si j'ai bien compris ?) :

// JavaScript Document for Illustrator
var dec = 20;

if (app.documents.length > 0) {
  var docRef = app.activeDocument;
  var selectedItems = selection;
  var nbObjSelect = selectedItems.length;
    if (nbObjSelect) {
      var rep, iObj, newtop;
      var TabTop = [];
          rep = prompt("Tolérance ?", dec);
          dec= rep*1;
            for (var i = 0; i < nbObjSelect; i++) {
              iObj = selectedItems;
              TabTop.push([iObj.top,i])
            }
          TabTop.sort();
          TabTop.reverse(); //alert(TabTop.join("\r"));
          newtop =  TabTop[0][0];
          docRef.layers.add();
          nbLayers = docRef.layers.length;
            for(i = 0, k = nbLayers-1; i < nbObjSelect; i++) {
              if (newtop > TabTop[0]-dec && newtop < TabTop[0]+dec) {
                iObj = selectedItems[TabTop[1]];
                iObj.move(docRef.layers[0],ElementPlacement.PLACEATEND);
                docRef.layers[0].name = "Rang "+k;
              }
              else {
                newtop = TabTop[0]; k++; i--;
                docRef.layers.add();
              }
            }
      var layerAct, nbObjLayer, n, nObj, j, jObj;
      var TabLeft = [];
          for(i = 0; i < k; i++) {
            layerAct = docRef.layers;
            nbObjLayer = layerAct.pageItems.length;
              for(n = 0; n < nbObjLayer; n++) {
                nObj = layerAct.pageItems;
                TabLeft.push([nObj.left,nObj]);
              }
            TabLeft.sort(); //TabLeft.revers(); alert(TabLeft.join("\r"));
              for(j = 0; j < nbObjLayer; j++) {
                jObj = TabLeft[1];
                jObj.zOrder(ZOrderMethod.SENDTOBACK);
              }
            TabLeft = [];
          }
    }
    else alert("Vous n'avez rien sélectionné !","De Elleere");
}
else alert("Pour l'exécution de ce sript un document doit être ouvert !","Script Alerte de Elleere !");


//-------------------------------------------------------------

de LR elleere

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Thank you, your script seems doing that I need. Tolerance value I think is fine. But there is some problems:

  1. It creates last layer (virtual row) in top of the list.
  2. Each object in the row should be sorted from right to left
  3. it creates layers with objects. In finale will be good if all sorted objects will be in one layer

see pic below

Test1-Simple.jpg

Here some test ai files.

[link removed by moderator]

You can test by your self. I will be glad if you can fix this problem for me!

Thanks in advance!

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Bonjour Dever,

The link is infected attention !!

Me contacter par mail (exemple enregistré sous  Illustrator Version CS6).

LR

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Hello LR

Zippyshare injects some ads and it can be infected, sorry about it

here is Wetransfer link with CS6 files to test

https://we.tl/t-OXgD7GfrDw

Thanks,

Alex

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Hello Rene,

Still did not get an Email from you. Can you post working script here?

Thanks

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 05, 2020 Sep 05, 2020

Copy link to clipboard

Copied

This script looks like exactly what I need but it also gives me an error... am I doing somthing wrong?Screen Shot 2020-09-05 at 4.51.00 PM.png

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

I cannot see why the above two scripts are not working.  You could try the snippet below, but it's for all pageItems in the document, not selected items.  It doesn't work for selected items and again I'm unsure why.  (I would be grateful if someone could advise on why it works on the "pageItems" or "pathItems" collection but not on the "selection" collection.)

 

var items = app.activeDocument.pageItems;
for (var i = 0; i < items.length - 1; i++) {
  for (var j = 0; j < items.length - i - 1; j++) {
    if (items[j].top > items[j + 1].top) {
      items[j].moveAfter(items[j+1]);
    }
  }
}

 

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Thanks!

Unfortunately,...

 

topMost.zOrder is not a function

 

(Maybe changes in the API in the meanwhile?)

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

function test() {
    if (!app.documents.length) {
        alert("You must have a document open.");
        return;
    }
    var docRef = app.activeDocument;
    var sel = docRef.selection;
    if (!sel.length) {
        alert("You must make a selection.");
        return;
    }
    function sortVertically(items) {
        var topMost,curY,delIndex,curItem,tempItems = [];
        for (var x = 0, len = items.length; x < len; x++) {
            tempItems.push(items[x]);
        }
        while (tempItems.length) {
            topMost = tempItems[0];
            curY = topMost.top;
            delIndex = 0;
            for (var x = 1, len = tempItems.length; x < len; x++) {
                curItem = tempItems[x];
                if (curItem.top > curY) {
                    topMost = curItem;
                    curY = curItem.top;
                    delIndex = x;
                }
            }
            topMost.zOrder(ZOrderMethod.BRINGTOFRONT);
            tempItems.splice(delIndex, 1);
        }
    }
    sortVertically(sel);
}
test();

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Thanks, @femkeblanco (et al, of course): this works!

And thanks for posting it as pre-formatted text, that makes it a lot easier to read, copy and paste.
Comparing your script witht the original, I'm surprised the original worked at all for anybody.

I notice the same kind of change in two locations:

tempItems.push(items); →→→ tempItems.push(items[x]); 

and

curItem = tempItems;   →→→   curItem = tempItems[x]; 

 

Would the original have worked accidentally with grouped items?

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Based on the work by @DilliamWowling and @femkeblanco, I wrote a more verbosely commented script and added the possibility to sort by any property. For sake of legibility, I used the JavaScript 'sort' function. I hope this helps.

function main() {
  // Check if there is an open document with a selection
  if (!app.documents.length) {
    alert("You must have a document open.");
    return;
  }

  var docRef = app.activeDocument;
  var sel = docRef.selection;

  if (!sel.length) {
    alert("You must make a selection.");
    return;
  }

  // Prompt the user for the sorting criterion
  var criterion = prompt("What property do you want to sort by? E.g. top, left, width, height, opacity, name:", "top");

  // If the property has a minus sign, the user wants to sort in reverse order. (*1)
  var sortOrder = 1;
  if (criterion[0] === "-") {
    sortOrder = -1;
    criterion = criterion.substr(1);
  }

  //  Make a copy of the array containing the selection:
  var items = [];
  for (var i = 0; i < sel.length; i++) {
    items.push(sel[i]);
  }

  // Sort the array by the criterion
  items = items.sort(dynamicSort(criterion));

  // iterate the array in reverse order while moving every element to the top:
  for (var i = items.length - 1; i >= 0; i--) {
    if (sortOrder === 1) {
      items[i].zOrder(ZOrderMethod.BRINGTOFRONT);
    } else {
      items[i].zOrder(ZOrderMethod.SENDTOBACK);
    }
  }
}

// Sorting function
function dynamicSort(property) {
  // Adapted from: https://stackoverflow.com/a/4760279/960592 (Credit: Ege Özcan)
  // (Adobe's Javascript doesn't seem to like double ternary operator)

  return function (a, b) {
    if (a[property] < b[property]) {
      return -1;
    }

    if (a[property] > b[property]) {
      return 1;
    }

    return 0;
  }
}


main();

/* 
Note: It *should* be possible to just reverse the array (items.reverse() ) or to change the sorting order in
the sorting function, but I couldn't get either method to work. This is a work-around.
*/

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

I should have made it clear that the above was @DilliamWowling 's script, I just updated it. It is my understanding that migrating to the present forum in late 2019 impaired scripts, including causing loss of indices of elements. The script was evidently working up until that point.

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

Is that also the reason that there is no formatting on code in older posts?

Likes

Translate

Translate

Report

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

Copy link to clipboard

Copied

LATEST

That is what I presume. 

Likes

Translate

Translate

Report

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