Display Top Three Items in a List by Data Attribute

I have a list that is sorted by JS using data attributes. The list appears like this:

<li data-sortm="4">Migraines</li>
<li data-sortm="2">Stress</li>
<li data-sortm="2">Depression</li>
<li data-sortm="1">Anxiety</li>
<li data-sortm="1">Lack of Appetite</li>
<li data-sortm="1">Muscle Spasms</li>
<li data-sortm="0">Nausea</li>
<li data-sortm="0">Insomnia</li>
<li data-sortm="0">Pain</li>
<li data-sortm="0">PMS</li>
<li data-sortm="0">Seizures</li>
<li data-sortm="0">Fatigue</li>

What I would like to do is display the top three items and hide or remove the rest of the list. For example in the list above the top three would look like this:

  • Change data-src to src via jquery
  • jQuery select data attributes with common keyword
  • jQuery select elements which contain specified item in an array data attribute
  • querySelectorAll to find matching data-attribute
  • Create an Array from a single HTML5 “data-” attribute
  • Best practices for data association with HTMLElement objects?
  • <li data-sortm="4">Migraines</li>
    <li data-sortm="2">Stress</li>
    <li data-sortm="2">Depression</li>
    

    There is one catch, while I would like the top three displayed if we have a setup like this:

    <li data-sortm="4">Migraines</li>
    <li data-sortm="3">Pain</li>
    <li data-sortm="2">Stress</li>
    <li data-sortm="2">Depression</li>
    

    I would want to show all four since the last two are the same number.

    How do I do this using jQuery?

    I have considered using RegEx as I think that may be a way but RegEx is not an area I find easy to use.

    Here is the code I am using to sort the list:

    $(".medical-list li").sort(sort_li_medical).appendTo('.medical-list');
      function sort_li_medical(a, b){
        return ($(a).data('sortm')) < ($(b).data('sortm')) ? 1 : -1;    
    }
    

    Note: I am using v2.1 of jQuery.

  • JQuery Retrive data-attribute from on click function
  • parseInt returns NaN when it should be a number?
  • Storing data in the DOM
  • Do html5 data attributes need a value?
  • Classes vs data attribute, auto field initialiser
  • jQuery: Select data attributes that aren't empty?
  • 4 Solutions collect form web for “Display Top Three Items in a List by Data Attribute”

    Here we go, I made a JSFiddle with what you’re looking for.

    Made use of the .filter() function and applied a .hide() to all that don’t match the top tier.

    var min = 0;
    $(".medical-list li").filter( function(k, v) {
        if( k < 3 ) { //Top 3 will be shown
            min = parseInt($(v).data('sortm'));
            return false;
        } else //Anything else must equal to third one, or it's filtered
            return min > parseInt($(v).data('sortm'));
    }).hide(); //Hide all that are not in the top 3
    

    Of course, you would place this after your li‘s are sorted.

    var prevVal = -1;
    
    var $collection = $('li[data-sortm]');
    var $collectionToRemove = $collection.filter(function(index) {
      var thisVal = $(this).data('sortm');
    
      // if this is the 4 item or more and prev value != thisValue
      if ( index > 3 && prevVal != thisVal ) {
        prevVal = thisVal;
        return true;
      }
      prevVal = thisVal;
      return false;
    });
    
    $collectionToRemove.remove();
    

    Not the fastest and not the prettiest code but i hope it explains the process

    Fiddle: http://jsfiddle.net/Wj6gP/

    Pretty straightforward – count the # of times each number is used, mark the top 3+ with a class and then hide anything without it.

    var unique_keys = {};
    $.map($('li'), function(a) {    
        unique_keys[$(a).data('sortm')] = unique_keys[$(a).data('sortm')] + 1 || 1; 
    });
    
    var sorted = Object.keys(unique_keys).sort().reverse();
    
    var total = 0;
    for (var i = 0; i < sorted.length; i++) { 
        $('li[data-sortm=' + sorted[i] + ']').addClass('show');
        total += unique_keys[sorted[i]];
        if(total >= 3) {
             break;   
        }
    }
    
    $('li:not(.show)').hide();
    

    Try this:

    var count = 0;
    var currentTop = -1;
    $('li[data-sortm]').each(function() {
        var $this = $(this);
        var sortm = $this.data('sortm');
        if (count >= 3) {
            if (count == 3 && currentTop == sortm) {
                currentTop = sortm;
                return;
            }
            $this.remove();
            return;
        }
        count++;
        currentTop = sortm;
    });
    

    Demo Link