0

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

<section class="box explore">
<div id="ProductContainer"  class="row">
        <div id="1232132" data-name="B" data-category="Category_A" class="explore-cell">
         <h>B</h>
         <p>Category_A</p>
        </div>
    <div id="123" data-name="A" data-category="Category_A" class="explore-cell">
        <h>A</h>
        <p>Category_A</p>
    </div>
    <div id="1232152351" data-name="C" data-category="Category_A" class="explore-cell">
        <h>C</h>
        <p>Category_A</p>
    </div>
    <div id="12342341" data-name="E" data-category="Category_B" class="explore-cell">
        <h>E</h>
        <p>Category_B</p>
    </div>
    <div id="1325321" data-name="D" data-category="Category_B" class="explore-cell">
        <h>D</h>
        <p>Category_B</p>
    </div>

</div>

java

$('div').sort(function (a, b) {

  var contentA = $(a).attr('data-name');
  var contentB = $(b).attr('data-name');
  return (contentA < contentB) ? -1 : (contentA > contentB) ? 1 : 0;

})

Jsfiddle http://jsfiddle.net/w8gkshue/

if someone can point me in the right direct on how to best sort either by Product Name or Category.

Updated hope this gives better explination

foO
  • 1
  • 1
  • Are you trying to re-position the dom elements based on your sorting? – LouisK Dec 04 '14 at 22:28
  • the divs generate a grid view of rows and cells, with the cells being out of order. I was trying to use http://stackoverflow.com/questions/6133723/sort-divs-in-jquery-based-on-attribute-data-sort as a starting point but did not work with strings – foO Dec 04 '14 at 22:30

4 Answers4

1

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

Joel Ibaceta
  • 236
  • 3
  • 15
  • would would be the best mtehod to attech to the div id rather then class there are multiple row classes – foO Dec 04 '14 at 23:04
  • weird I will play around I can't get it to work local but that is a good start thanks brother – foO Dec 04 '14 at 23:23
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>
plalx
  • 42,889
  • 6
  • 74
  • 90
0

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.

musicinmyhead
  • 1,466
  • 9
  • 11
0

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');
Community
  • 1
  • 1
axelduch
  • 10,769
  • 2
  • 31
  • 50
  • There's no need to detach the `$products` before appending them. Also, it's the `$container` you want to detach before appending the products to avoid multiple reflows. – plalx Dec 05 '14 at 14:31