Question

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:

<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.

Was it helpful?

Solution

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.

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top