Sorting products by name or price 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:

&lt;select id="sorting" onchange="selectionChange()"&gt;
      &lt;option value="Sort By"&gt;Sort Products&lt;/option&gt;
      &lt;option value="Sort By Price" id="price"&gt;Sort By Price&lt;/option&gt;
      &lt;option value="Sort By A-Z" id="az"&gt;Sort By A-Z&lt;/option&gt;
      &lt;option value="Sort By Z-A" id="az"&gt;Sort By Z-A&lt;/option&gt;
&lt;/select&gt;
&lt;div class="products"&gt;
      &lt;div class="product-wrapper"&gt;
            &lt;div class="single-product"&gt;
                 &lt;a href="item-url"&gt;&lt;img src="path"/&gt;&lt;/a&gt;
                 &lt;a href=""&gt;text link&lt;/a&gt;
                 &lt;p&gt;$item price&lt;/p&gt;
            &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="product-wrapper"&gt;
            &lt;div class="single-product"&gt;
                 &lt;a href="item-url"&gt;&lt;img src="path"/&gt;&lt;/a&gt;
                 &lt;a href=""&gt;text link&lt;/a&gt;
                 &lt;p&gt;$item price&lt;/p&gt;
            &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;


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 &gt; bn) {
        return 1;
    }
    if(an &lt; 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 &gt; bn) {
        return 1;
    }
    if(an &lt; 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 &gt; bn) {
        return -1;
    }
    if(an &lt; 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.
All the sort functions follow the same pattern, with a few key differences:


A field to extract for comparison (.sortprice, .sort1)
A comparison function (numeric, alphabetic, ascending and descending)


These can be parameters for a general-purpose implementation:

sortHelper = function(search, comparator) {
    $('.product-wrapper').each(function() {
        var data = $(this).find(search).text();
        $(this).attr('data-name', data);
    });

    var $products = $('.products'),
        $singleProduct = $('.product-wrapper');

    $singleProduct.sort(comparator);

    $singleProduct.detach().appendTo($products);
};


The price comparator function can be implemented simpler than you did,
considering that it doesn't need to return precisely -1, 1 values,
any other negative and positive values would be fine:

var cmpPrice = 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, ""));
    return numberA - numberB;
};


The string comparator function can be much like it was:

var cmpName = function(a, b) {
    var an = a.getAttribute('data-name');
    var bn = b.getAttribute('data-name');
    if (an &gt; bn) {
        return 1;
    }
    if (an &lt; bn) {
        return -1;
    }
    return 0;
});


The string comparator in descending order can be implemented in terms of the other one in ascending order:

var cmpNameDesc = function(a, b) {
    return cmpName(b, a);
});


And then the main function can be implemented in terms of these helpers:

selectionChange = function() {
    var selectResult = $("#sorting").val();

    if (selectResult == "Sort By Price") {
        sortHelper('.sortprice', cmpPrice);
    } else if (selectResult == "Sort By A-Z") {
        sortHelper('.sort1', cmpName);
    } else if (selectResult == "Sort By Z-A") {
        sortHelper('.sort1', cmpNameDesc);
    }
};