Search code examples
javascripthtmldomdocumentfragment

Reorder elements layout according to array with elements id's


I need to perform the following task : There are two 'ul' elements containing some 'li' with unique id's.

    <div id="sr">
        <ul id="li-fav">
            <li id="app-1">a</li>
            <li id="app-2">b</li>
            <li id="app-3">c</li>
        </ul>
        <ul id="li-rest">
            <li id="app-4">d</li>
            <li id="app-5">e</li>
            <li id="app-6">f</li>            
        </ul>
    </div>

Using getElementsOrder function I achieve the resulting arrays containing number id's of elements:

function getElementsOrder(){
    var f, r,
    fLi = [], rLi = [];

    f = document.getElementById('apps-fav').childElementNodes;
    console.log(f);
    for(var i=0, l=f.length; i<l; i+=1){
        fLi.push(f[i].id.split('-')[1]);
    }
    r = document.getElementById('apps-rest').childElementNodes;
    for(i=0, l=r.length; i<l; i+=1){
        rLis.push(r[i].id.split('-')[1]);
    }

    return {'fav': fLi, 'rest': rLi};
}

// {'fav': [1, 2, 3], 'rest': [4, 5, 6]}

Now I'd like to have the ability of reordering li elements in both ul's when reading data from differently sorted arrays, ie:

//{'fav': [3, 4, 1], 'rest': [2, 5, 6]}

How to do this in most browser-friendly way ? Using document fragment ? What shold be the steps ? I have the sample on jsfiddle:

http://jsfiddle.net/PTx3f/


Solution

  • You can just move the li elements along the lines of:

    var favs = obj.fav;  // where obj is the object returned by getElementsOrder() 
    var i = favs.length;
    var ul = document.getElementById('li-fav');
    
    while (i--) {
      ul.insertBefore(document.getElementById('app-' + favs[i]), ul.firstChild);  
    }
    
    var rest = obj.rest;
    i = rest.length;
    ul = document.getElementById('li-rest');
    
    while (i--) {
      ul.insertBefore(document.getElementById('app-' + rest[i]), ul.firstChild);  
    }
    

    Note the decrementing count so that the elements end up in the right order using insertBefore. The code should be refactored to remove the duplication of logic.

    Edit - refactored

    function doStuff() {
      var i, ids, list, ul; 
    
      for (list in obj) {
    
        if (obj.hasOwnProperty(list)) {
          ids = obj[list];  
          i = ids.length;
          ul = document.getElementById('li-' + list);
    
          while (i--) {
            ul.insertBefore(document.getElementById('app-' + ids[i]), ul.firstChild);  
          }
        }
      }
    }
    

    Added a hasOwnProperty test to protect from inherited enumerable properties.