methuselah
methuselah

Reputation: 13206

Sort DOM elements in array

I have an array which tracks the movement of elements on the DOM. Therefore, at any point, the DOM (represented by the variable components) might look as follow due to intermittent changes by the user:

["app-builder-placeholder", 
 "app-builder-placeholder", 
 "app-builder-footer", 
 "app-builder-navbar", 
 "app-builder-placeholder"] 

["app-builder-placeholder", 
 "app-builder-placeholder", 
 "app-builder-navbar", 
 "app-builder-footer", 
 "app-builder-placeholder"]

["app-builder-placeholder", 
 "app-builder-placeholder", 
 "app-builder-footer", 
 "app-builder-navbar", 
 "app-builder-placeholder"]

["app-builder-navbar", 
 "app-builder-placeholder",
 "app-builder-placeholder", 
 "app-builder-footer", 
 "app-builder-placeholder"]

I would re-sort the array to guarantee the following: - app-builder-placeholder item comes before/after a "non" app-builder-xxx item - two app-builder-placeholder items cannot follow each other

So in effect, the above should really look like this:

["app-builder-placeholder",
 "app-builder-navbar",
 "app-builder-placeholder",
 "app-builder-footer",
 "app-builder-placeholder"]

or

["app-builder-placeholder",
 "app-builder-footer",
 "app-builder-placeholder",
 "app-builder-navbar",
 "app-builder-placeholder"]

as these are the only two possible ways it can be sorted.

My current code which tracks the update of the DOM is as follows. How would I extend it so that the array is sanitised accordingly. In a situation where the criteria is not met, placeholder items can be created on the spot before and after the non placeholder items so that the array is re-crafted to fit the criteria.

this.options = {
  onUpdate: function (e: any) {
    let components = [];
    for(let i = 0; i < e.target.children.length; i++) {
      components.push(e.target.children[i].children[0].children[0].localName)
    }
    console.log(components);
  }
};

Upvotes: 0

Views: 66

Answers (1)

Klaycon
Klaycon

Reputation: 11080

Here's a way you could do it using plenty of array helpers:

let counter = components.length, placeholderName = "app-builder-placeholder";
//calculate new array size with required number of placeholders
let newLength = components.filter(c => c != placeholderName).length*2+1;

//remove excess placeholders
while(newLength > components.length)
  components.splice(components.lastIndexOf(placeholderName), 1);

//add placeholders if needed
components.length = newLength;
components.fill(placeholderName,counter);

//iterate and move placeholders to proper locations, preserving order
for(let i = 0, counter = 0; i < components.length; i++)
  if(components[i] == placeholderName)
    components.splice((counter++)*2, 0, components.splice(i, 1)[0]);

Upvotes: 1

Related Questions