Lets preface this by saying that when it comes to javascript, I am a hack. I make what I need happen by cobbling together crappy, inefficient, redundant code. I want to get better. Recently I was asked if I could make a set of elements on a page sort-able by price, A-Z and Z-A. The code on the page looks something like the below:
<select id="sorting" onchange="selectionChange()">
<option value="Sort By">Sort Products</option>
<option value="Sort By Price" id="price">Sort By Price</option>
<option value="Sort By A-Z" id="az">Sort By A-Z</option>
<option value="Sort By Z-A" id="az">Sort By Z-A</option>
</select>
<div class="products">
<div class="product-wrapper">
<div class="single-product">
<a href="item-url"><img src="path"/></a>
<a href="">text link</a>
<p>$item price</p>
</div>
</div>
<div class="product-wrapper">
<div class="single-product">
<a href="item-url"><img src="path"/></a>
<a href="">text link</a>
<p>$item price</p>
</div>
</div>
</div>
I was able to make things work by assigning a sort class to the text link and the price "p" tag, listen for onchange from the dropdown and when it fired either the price or the name of the item was assigned as an attribute to the containing product wrapper, then the wrappers are sorted using a simple sort function. My working but embarrassing attempt is below.
jQuery(document).ready(function( $ ) {
sortPrice = function(){
$('.product-wrapper').each(function(){
var data1 = $(this).find(".sortprice").text();
$(this).attr('data-name', data1);
});
var $products = $('.products'),
$singleProduct = $('.product-wrapper');
$singleProduct.sort(function(a,b){
var an = a.getAttribute('data-name');
var bn = b.getAttribute('data-name');
var numberA = Number(an.replace(/[^0-9\.]+/g,""));
var numberB = Number(bn.replace(/[^0-9\.]+/g,""));
an = numberA;
bn = numberB;
if(an > bn) {
return 1;
}
if(an < bn) {
return -1;
}
return 0;
});
$singleProduct.detach().appendTo($products);
};
sortA = function(){
$('.product-wrapper').each(function(){
var data1 = $(this).find(".sort1").text();
$(this).attr('data-name', data1);
});
var $products = $('.products'),
$singleProduct = $('.product-wrapper');
$singleProduct.sort(function(a,b){
var an = a.getAttribute('data-name');
var bn = b.getAttribute('data-name');
if(an > bn) {
return 1;
}
if(an < bn) {
return -1;
}
return 0;
});
$singleProduct.detach().appendTo($products);
};
sortZ = function(){
$('.product-wrapper').each(function(){
var data1 = $(this).find(".sort1").text();
$(this).attr('data-name', data1);
});
var $products = $('.products'),
$singleProduct = $('.product-wrapper');
$singleProduct.sort(function(a,b){
var an = a.getAttribute('data-name');
var bn = b.getAttribute('data-name');
if(an > bn) {
return -1;
}
if(an < bn) {
return 1;
}
return 0;
});
$singleProduct.detach().appendTo($products);
};
selectionChange = function(){
var selectResult = $("#sorting").val();
if(selectResult == "Sort By Price"){
sortPrice();
} else if(selectResult == "Sort By A-Z"){
sortA();
} else if(selectResult == "Sort By Z-A"){
sortZ();
}
};
});
I would be eternally indebted to whoever will show me what an elegant version would look like and maybe how and where I would add error handling.
$("select").tinysort()
et voila \$\endgroup\$$singleProduct.sort(function(a,b)
? there is nosort
method in jQuery... \$\endgroup\$.sort1
, .sortprice
, etc. \$\endgroup\$