Reputation: 538
I've created a 4 way sorting in jQuery on my data-attributes. But when I click on a sort option, it always sorts alphabetically from A-Z for one time. When I click another time on a sorting, it doesn't do anything.
When I do a console log to see on which item is click, I get the following results:
za
az
or
1-10
za
az
So it always sorts from A-Z at the end. But honestly don't know why.
This is the example of my HTML:
<div class="sort">
<span class="sort__item" id="js-az">A-Z</span>
<span class="sort__item" id="js-za">Z-A</span>
<span class="sort__item" id="js-1-10">1-10</span>
<span class="sort__item" id="js-10-1">10-1</span>
</div>
<div class="row js-songs-sortable" id="all-song-list">
<div class="col-md-4 col-sm-12" data-count="5" data-name="Strange Days">
content
</div>
<div class="col-md-4 col-sm-12" data-count="1" data-name="Rock Bottom">
content
</div>
<div class="col-md-4 col-sm-12" data-count="1" data-name="Moutain">
content
</div>
<div class="col-md-4 col-sm-12" data-count="3" data-name="Mad Sun">
content
</div>
<div class="col-md-4 col-sm-12" data-count="10" data-name="Another Ugly Tune">
content
</div>
</div>
And this is my jQuery code:
jQuery('body').on('click', '.sort #js-az', function(){
jQuery(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(a,b){
return (jQuery(b).data('name')) < (jQuery(a).data('name')) ? 1 : -1;
}
});
jQuery('body').on('click', '.sort #js-za', function(){
jQuery(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(b,a){
return (jQuery(b).data('name')) < (jQuery(a).data('name')) ? 1 : -1;
}
});
jQuery('body').on('click', '.sort #js-1-10', function(){
jQuery(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(a,b){
return (jQuery(b).data('count')) < (jQuery(a).data('count')) ? 1 : -1;
}
});
jQuery('body').on('click', '.sort #js-10-1', function(){
jQuery(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(b,a){
return (jQuery(b).data('count')) < (jQuery(a).data('count')) ? 1 : -1;
}
});
You can find the live preview here: https://mpdb.space/mp-songs/
Upvotes: 1
Views: 101
Reputation: 11447
The issue with your code is that you are using .data
whereas you need to use .attr()
.
jQuery('body').on('click', '.sort #js-az', function() {
jQuery(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(a, b) {
return (jQuery(b).attr('data-name')) < (jQuery(a).attr('data-name')) ? 1 : -1;
}
});
jQuery('body').on('click', '.sort #js-za', function() {
jQuery(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(b, a) {
return (jQuery(b).attr('data-name')) < (jQuery(a).attr('data-name')) ? 1 : -1;
}
});
jQuery('body').on('click', '.sort #js-1-10', function() {
jQuery(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(a, b) {
return (parseInt(jQuery(b).attr('data-count'))) < parseInt((jQuery(a).attr('data-count'))) ? 1 : -1;
}
});
jQuery('body').on('click', '.sort #js-10-1', function() {
jQuery(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(b, a) {
return parseInt(jQuery(b).attr('data-count')) < parseInt(jQuery(a).attr('data-count')) ? 1 : -1;
}
});
.sort {
border-radius: 5px;
background-color: #eee;
display: inline-block;
margin-bottom: 1rem;
}
.sort span {
padding: 1rem;
cursor: pointer;
transition: all 0.3s;
display: inline-block;
}
.sort span:hover {
background-color: rgba(0, 0, 0, 0.1);
}
.row>div {
padding: 0.5rem;
}
.row>div::after {
content: "data-count= " attr(data-count) " data-name= " attr(data-name);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="sort">
<span class="sort__item" id="js-az">A-Z</span>
<span class="sort__item" id="js-za">Z-A</span>
<span class="sort__item" id="js-1-10">1-10</span>
<span class="sort__item" id="js-10-1">10-1</span>
</div>
<div class="row js-songs-sortable" id="all-song-list">
<div class="col-md-4 col-sm-12" data-count="5" data-name="Strange Days">
</div>
<div class="col-md-4 col-sm-12" data-count="1" data-name="Rock Bottom">
</div>
<div class="col-md-4 col-sm-12" data-count="1" data-name="Moutain">
</div>
<div class="col-md-4 col-sm-12" data-count="3" data-name="Mad Sun">
</div>
<div class="col-md-4 col-sm-12" data-count="10" data-name="Another Ugly Tune">
</div>
</div>
Also, you can change your code little bit for maintainability and readability. See this example:
jQuery('body').on('click', '.sort__item', function() {
const id = jQuery(this).attr("id");
jQuery(".js-songs-sortable > div").sort(function(a, b) {
let firstEl = jQuery(a);
let secondEl = jQuery(b);
let $return = 0;
switch (id) {
case "js-az":
$return = (firstEl.attr('data-name') > secondEl.attr('data-name')) ? 1 : -1;
break;
case "js-za":
$return = (firstEl.attr('data-name') < secondEl.attr('data-name')) ? 1 : -1;
break;
case "js-1-10":
$return = (parseInt(firstEl.attr('data-count')) > parseInt(secondEl.attr('data-count'))) ? 1 : -1;
break;
case "js-10-1":
$return = (parseInt(firstEl.attr('data-count')) < parseInt(secondEl.attr('data-count'))) ? 1 : -1;
break;
}
return $return;
}).appendTo('.js-songs-sortable');
});
.sort {
border-radius: 5px;
background-color: #eee;
display: inline-block;
margin-bottom: 1rem;
}
.sort span {
padding: 1rem;
cursor: pointer;
transition: all 0.3s;
display: inline-block;
}
.sort span:hover {
background-color: rgba(0, 0, 0, 0.1);
}
.row>div {
padding: 0.5rem;
}
.row>div::after {
content: "data-count= " attr(data-count) " data-name= " attr(data-name);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="sort">
<span class="sort__item" id="js-az">A-Z</span>
<span class="sort__item" id="js-za">Z-A</span>
<span class="sort__item" id="js-1-10">1-10</span>
<span class="sort__item" id="js-10-1">10-1</span>
</div>
<div class="row js-songs-sortable" id="all-song-list">
<div class="col-md-4 col-sm-12" data-count="5" data-name="Strange Days">
</div>
<div class="col-md-4 col-sm-12" data-count="1" data-name="Rock Bottom">
</div>
<div class="col-md-4 col-sm-12" data-count="1" data-name="Moutain">
</div>
<div class="col-md-4 col-sm-12" data-count="3" data-name="Mad Sun">
</div>
<div class="col-md-4 col-sm-12" data-count="10" data-name="Another Ugly Tune">
</div>
</div>
Upvotes: 0
Reputation: 1335
Data-attributes always return a string (by the way, input fields as well, common mistake), which comparison result differs from numbers comparison:
console.log( "9" > "111" ) // true
console.log( "310" > "31" ) // true
You have to convert them into number with unary +
:
( +$(a).data('count') < +$(b).data('count') ) ? -1 : 1;
But because you need to return any positive or negative number, can just subtract them. The -
operator will automatically turn them into numbers.
$('#js-az').on('click', function() {
$(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(a, b) {
return ( $(a).data('name') < $(b).data('name') ) ? -1 : 1;
}
});
$('#js-za').on('click', function() {
$(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(a, b) {
return ( $(a).data('name') > $(b).data('name') ) ? -1 : 1;
}
});
$('#js-1-10').on('click', function() {
$(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(a, b) {
return $(a).data('count') - $(b).data('count');
}
});
$('#js-10-1').on('click', function() {
$(".js-songs-sortable > div").sort(sort_li).appendTo('.js-songs-sortable');
function sort_li(a, b) {
return $(b).data('count') - $(a).data('count')
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="sort">
<span class="sort__item" id="js-az">A-Z</span>
<span class="sort__item" id="js-za">Z-A</span>
<span class="sort__item" id="js-1-10">1-10</span>
<span class="sort__item" id="js-10-1">10-1</span>
</div>
<div class="row js-songs-sortable" id="all-song-list">
<div data-count="5" data-name="Strange Days">data-count="5" data-name="Strange Days"</div>
<div data-count="1" data-name="Rock Bottom">data-count="1" data-name="Rock Bottom"</div>
<div data-count="1" data-name="Moutain">data-count="1" data-name="Moutain"</div>
<div data-count="3" data-name="Mad Sun">data-count="3" data-name="Mad Sun"</div>
<div data-count="10" data-name="Another Ugly Tune">data-count="10" data-name="Another Ugly Tune"</div>
</div>
And shortened version of your code:
var funcStorage = {
az: (a, b) => $(a).data('name') < $(b).data('name') ? -1 : 1,
za: (a, b) => $(a).data('name') > $(b).data('name') ? -1 : 1,
"1-10": (a, b) => $(a).data('count') - $(b).data('count'),
"10-1": (a, b) => $(b).data('count') - $(a).data('count'),
}; // If this seems `Alien-code`, Google → JS objects, JS arrow functions
// (a,b) => a - b The same
// function (a,b) { return a - b } thig.
$('.sort__item').each(function(){
$(this).on('click', function(){
var func = funcStorage[ this.id.replace("js-","") ];
// in fact, you don't need id, could store the sort key in data-sort
$(".js-songs-sortable > div").sort(func).appendTo('.js-songs-sortable');
$('.sort__item.active').removeClass('active');
$(this).addClass('active');
});
});
.sort__item {
display: inline-block;
cursor: pointer;
border: 2px solid orange;
margin: 5px;
padding: 5px;
}
.sort__item.active { background-color: orange; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="sort">
<span class="sort__item" id="js-az">A-Z</span>
<span class="sort__item" id="js-za">Z-A</span>
<span class="sort__item" id="js-1-10">1-10</span>
<span class="sort__item" id="js-10-1">10-1</span>
</div>
<div class="row js-songs-sortable" id="all-song-list">
<div data-count="5" data-name="Strange Days">data-count="5" data-name="Strange Days"</div>
<div data-count="1" data-name="Rock Bottom">data-count="1" data-name="Rock Bottom"</div>
<div data-count="1" data-name="Moutain">data-count="1" data-name="Moutain"</div>
<div data-count="3" data-name="Mad Sun">data-count="3" data-name="Mad Sun"</div>
<div data-count="10" data-name="Another Ugly Tune">data-count="10" data-name="Another Ugly Tune"</div>
</div>
Upvotes: 1
Reputation: 184
As documented here, by default, the sort()
method sorts the values as strings in alphabetical and ascending order. However you can modify its behaviour by passing a compare function. You have not specified the result you are wanting to achieve so you will have to create a function with the desired sorting logic.
Upvotes: 1