Skip to content Skip to sidebar Skip to footer

Sort Child Div Based On Data Attribute

Trying to sort children div based on data attributes The html code below is being generated by a CM and the data can be retrieved in any random order. the html code is

Solution 1:

EDIT: I missed the jQuery tag... leaving the answer still.

var productCt = document.getElementById('ProductContainer'),
    reInsertProductCt = tempRemove(productCt);


[].slice.call(productCt.children)
  .sort(function (a, b) {
    var aName = a.dataset.name,
        bName = b.dataset.name;
  
    return aName < bName? -1 : +(aName > bName);
  })
  .forEach(productCt.appendChild.bind(productCt));

reInsertProductCt();





function tempRemove(el) {
    var parent = el.parentNode,
        nextSibling = el.nextSibling;
  
    parent.removeChild(el);
  
    return function () {
        if (nextSibling) parent.insertBefore(el, nextSibling);
        else parent.appendChild(el);
    };
}
<div id="ProductContainer"  class="row">
        <div id="1232132" data-name="B" data-category="Category_A" class="explore-cell">
         <h>TEST NAME B</h>
         <p>TEST</p>
        </div>
    <div id="123" data-name="A" data-category="Category_A" class="explore-cell">
        <h>TEST NAME A</h>
        <p>TEST</p>
    </div>
    <div id="1232152351" data-name="C" data-category="Category_A" class="explore-cell">
        <h>TEST NAME C</h>
        <p>TEST</p>
    </div>
    <div id="12342341" data-name="E" data-category="Category_B" class="explore-cell">
        <h>TEST NAME E</h>
        <p>TEST</p>
    </div>
    <div id="1325321" data-name="D" data-category="Category_B" class="explore-cell">
        <h>TEST NAME D</h>
        <p>TEST</p>
    </div>

</div>

Solution 2:

You can use .sort method like this

var $wrapper = $('#ProductContainer');

$wrapper.find('.explore-cell').sort(function (a, b) {
    return a.getAttribute('data-name') > b.getAttribute('data-name');
})
.appendTo( $wrapper );

But I don't sure about the cross browsing support


Solution 3:

Calling only sort on them won't actually visually change the DOM, it just returns a sorted collection. So basically you just need to get the collection, sort it, then return it. Something like this should work:

$('#ProductContainer > div').detach().sort(function (a, b) {
  var contentA = $(a).data('name');
  var contentB = $(b).data('name');
  return (contentA < contentB) ? -1 : (contentA > contentB) ? 1 : 0;
}).appendTo('#ProductContainer');

You'll want to make sure that you use the detach() method and not remove(), as detach() will retain all of the data and events associated with the collection items.


Solution 4:

Why choose to sort by category or by name when you can sort by both?

I tried to write a generic multisort function generator, which should also work with the native array sort function.

JSFIDDLE HERE

A function that generates the multisort, it takes two parameters.

  1. The column priority list order (first by category or by name? You decide).
  2. I also wanted a way to provide values for columns (since you might not retrieve them the same way for each of them), it is an object that describes for each column a function to retrieve data.

Here it is

function getMultisortFn(columns, provideColumnData) {
    return function (a, b) {
        for (var i = 0, l = columns.length; i < l; i++) {
            var column = columns[i];
            var aColumnData = provideColumnData[column.name](a, column.name);
            var bColumnData = provideColumnData[column.name](b, column.name);
            if (aColumnData !== bColumnData) {
                if (column.asc) {
                    return String.prototype.localeCompare.call(aColumnData, bColumnData);
                }

                return String.prototype.localeCompare.call(bColumnData, aColumnData);    
            }
        }
    };
}

Now this is the part where you actually use the multisort generated

function retrieveDataAttribute(item, attribute) {
    return $(item).data(attribute);
}

var $container = $('#ProductContainer'); 
var $products = $container.find('div');

var multisort = getMultisortFn([{
        name: 'category',
        asc: false
    }, {
        name: 'name',
        asc: true
    }], {
        name: retrieveDataAttribute,
        category: retrieveDataAttribute
    });



$products.sort(multisort);

And finally the DOM manipulation to apply the new order

$products.detach().appendTo($container);

EDIT thanks to plalx:

  $container.detach().append($products).appendTo('section.box.explore');

Post a Comment for "Sort Child Div Based On Data Attribute"