jQuery sorting of div elements based on count, and date/time (timestamp)

后端 未结 2 2056
感情败类
感情败类 2021-01-06 18:46

I currently use the sort function to sort my div elements based on the count value. Here\'s how it\'s being done now: (I\'m not sure if it\'s an efficient method or not..)

相关标签:
2条回答
  • 2021-01-06 18:58

    Performance:

    I'd highly recommend to cache the wrapped set before performing a sort().

    var $items = $('#list .list_item');
    $items.sort(sortDescending);
    

    That should give sizzle / your DOM a break like bigtime.

    To link your timestamp value aswell, you have to extend your sorting.

    function sortDescending(a, b) {
      var a_count = parseInt((a).find(".count").text(), 10),
          b_count = parseInt((b).find(".count").text(), 10),
          a_time  = parseInt((a).find(".timestamp").text(), 10),
          b_time  = parseInt((b).find(".count").text(), 10);
    
      return (a_count < b_count && a_time > b_time);
    };
    

    While writting this I actually realized that I wouldn't parse those values through element content. If you generate those nodes somewhere dynamically, it's maybe a better idea to use jQuerys $.data() method to store date and use/access that within your sorting method.

    0 讨论(0)
  • 2021-01-06 19:23

    Only the sort comparator function needs to change. I'm sure there are plugins available to do this, and you might want to take a look at them, but implementing what you want is fairly trivial. The sortDescending method gets two divs each time, and comparison must follow the criteria you've specified:

    1. First by count
    2. If count is equal, then by timestamp
    3. If timestamps are equal, then return 0

    Here's the ugly straightforward non-optimized version:

    function sortDescending(a, b) {
        if(getCount(a) < getCount(b)) {
            return -1;
        }
        else if(getCount(a) > getCount(b)) {
            return 1;
        }
        else if(getTimestamp(a) < getTimestamp(b)) {
            return -1;
        }
        else if(getTimestamp(a) > getTimestamp(b) {
            return 1;
        }
        else {
            return 0;
        }
    }
    

    If you see the if-else structure, it may seem obvious that you can genericize this approach to be able to handle any type of custom ordering. So here's a jab at a sortBy method that takes in a number callback functions, where each callback defines one sorting criteria.

    function sortBy() {
        var callbacks = arguments;
    
        return function(a, b) {
            for(var i = 0; i < callbacks; i++) {
                var value = callbacks[i](a, b);
                if(value != 0) {
                    return value;
                }
            }
            return 0;
        };
    }
    

    Then pass all criteria's as callbacks to this sortBy function. Here's a rough example for your code:

    function compareCount(a, b) {
        return getCount(a) - getCount(b);
    }
    
    function compareTimestamp(a, b) {
        return getTimestamp(a) - getTimestamp(b);
    }
    
    $("selector").sort(sortBy(compareCount, compareTimestamp));
    

    And while we are at it, let's also make a jQuery plugin out of this. It will have a nice and easy interface:

    $("parent selector").sortBy("child selector 1", "child selector 2", ...);
    

    The idea is to pass a jQuery selector that will select a node whose text will determine the value to sort by. We will give integers a higher priority and first try to sort numerically if both values are so, otherwise do a regular comparison.

    jQuery.fn.sortBy = function() {  
        var selectors = arguments;
    
        this.sort(function(a, b) {
            // run through each selector, and return first non-zero match
            for(var i = 0; i < selectors.length; i++) {
                var selector = selectors[i];
    
                var first = $(selector, a).text();
                var second = $(selector, b).text();
    
                var isNumeric = Number(first) && Number(second);
                if(isNumeric) {
                    var diff = first - second;
                    if(diff != 0) {
                        return diff;
                    }
                }
                else if(first != second) {
                    return first < second ? -1 : 1;
                }
            }
    
            return 0;
        });
    
        this.appendTo(this.parent());
    
        return this;
    };
    

    Use as

    $('#list .list_item').sortBy('.count', '.timestmap');
    

    See an example of the plugin here.

    Btw, none of this will actually sort the elements in the document itself. See this question for how to do that.

    0 讨论(0)
提交回复
热议问题