3

Im trying to sort a div structure based on a paramter using a small javscript i found.

It seems to not perform exactly as expected. I understand the sorting function is not parsing the values perfectly...

This is the sorting logic is use...

<script type="text/javascript">
    // Sorting Logic

    $(function() {
        $("a[href*=#]").click(function(e) {
            e.preventDefault();
            var liContents = [];
            $('#ProductPrice span[id*="ABSPrice"]').each(function() {
                liContents.push($(this).html());
            });
            liContents.sort(numOrdDesc);
            $('#ProductPrice span[id*="ABSPrice"]').each(function() {
                $(this).html(liContents.pop());
            });
        });
    });    
   function numOrdDesc(a, b) {
        return (parseInt(b) - parseInt(a));
}
    // End

of Sorting Logic Since i cannot exactly post the html i am going to add a link to the actual website where you can see this is action. Can anyone point out where i am going wrong?

http://www.absbiz.co.uk/Products/tabid/85/rvdsfcatid/Modems-437/Default.aspx

EDIT: Currently i think the sort is working, however i still cannot move the individual products. Only the prices get sorted and changed....

1
  • you are not passing any parameter to numOrdDesc function. And also, if it is a function call, it will not execute. Commented Jun 15, 2015 at 10:01

3 Answers 3

4
+100

I took at look at your live site and injected the sorting function you used in your question. I noticed a few things. Firstly, the strings you are passing into your compare function look like this:

"£38.89 ex. VAT"
"£19.93 ex. VAT"
"£44.44 ex. VAT"
...

So parseInt("£38.89 ex. VAT") will return NaN. No compare. We can adjust this to remove all non-decimal information, and also parse a float instead, like so:

parseFloat("£38.89 ex. VAT".replace(/[^0-9\.]/g, "")); // --> 38.89

However, this will sort the above price strings, but we don't have association information on the products to properly sort them in the DOM (yet). For that we need to adjust what you put into your array.


The strategy is to find all the top item containers using $('.ProductListProductItem') and push their html into an array. Sort the array such that the prices are found by $('#ProductPrice span[id*="ABSPrice"]') and stripped of non-decimal information. Each top item container is then repopulated with the html from the sorted array.

Essential code:

var liContents = [];
 // Push in all the product containers' innerHTML
$('.ProductListProductItem').each(function () {
   liContents.push($(this).html());
});

 // Use our new sorting routine
liContents.sort(numOrdDesc);

 // Replace the html of each top item container
$('.ProductListProductItem').each(function () {
   $(this).html(liContents.pop());
});

// Pass in jQuery elements, not strings
function numOrdDesc($a, $b) {
   // Get the price further down in the DOM
   var a = $('#ProductPrice span[id*="ABSPrice"]', $a).text();
   var b = $('#ProductPrice span[id*="ABSPrice"]', $b).text();
   return parseFloat(b.replace(/[^0-9\.]/g, "")) - parseFloat(a.replace(/[^0-9\.]/g, ""));
}

To verify this works, navigate to your live site and open DevTool > Console. Copy the above script and paste it into Console. Hit return, and note that the products are now sorted in ascending order. Enjoy.


Before:

Before

After:

After

Sign up to request clarification or add additional context in comments.

Comments

2

Your parseInt fails because of the pound sign. I'm guessing you want to strip that out in your sort function, and also use parseFloat instead since your prices are floating point numbers.

Try

function numOrdDesc(a, b) {
    return parseFloat(b.replace(/[^0-9\.]/g, "")) - parseFloat(a.replace(/[^0-9\.]/g, ""))
}

The replace pretty much removes everything that's not a digit or a dot from the string before attempting to parse it

// "£298.73".replace(/[^0-9\.]/g, "") -> "298.73"
// parseFloat("298.73") -> 298.73

3 Comments

Tried this approach. No luck
That's because you are doing the sorting in memory, not actually altering the DOM nodes (separate issue). To re-arrange the DOM nodes you'd have to detach them, do the sorting and add them back. Here is a simple example to get you started.
There is much, much more to the reason why the above code isn't working.
-1

You are missing parameters to the function, you can do it like this.

            liContents.sort(function(b, a) {
            return (parseInt(b) - parseInt(a));
        });

3 Comments

All you've done is replace his function reference with an anonymous function - which is bad practice in repetitive structures.
@AndreiNemes, I just showed him that he was missing the arguments to the function. The anonymous function is used inside a click event and not inside a loop, which is I think quite normal.
rashidkhan - he is not missing the function arguments. The function is passed by reference and receives the correct a and b when it's called by native code within Array.prototype.sort. All you've done is use an unnamed function reference versus an existing one. And to answer your second question, even though you're not creating the loop yourself, sorting is iterative. Try console logging inside your sorting function to see just how often it's called.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.