3

I have multiple list on a page. An example of a list looks like this:

<ul class="effects-list">
  <li data-sorte="2">creative</li>
  <li data-sorte="1">euphoric</li>
  <li data-sorte="2">uplifted</li>
  <li data-sorte="1">energetic</li>
  <li data-sorte="0">lazy</li>
  <li data-sorte="1">focused</li>
  <li data-sorte="2">happy</li>
  <li data-sorte="0">talkative</li>
  <li data-sorte="0">giggly</li>
  <li data-sorte="0">tingly</li>
  <li data-sorte="0">hungry</li>
  <li data-sorte="0">sleepy</li>
  <li data-sorte="0">aroused</li>
</ul>

I have a script that will remove all data-sorte that equals 0. After that is done, it sorts the list from highest to lowest (again by the numbers stored in data-sorte). It then takes the top three options and removes the rest.

Here is the script that does this:

$('*[data-sorte="0"]').remove();
    $(".effects-list li").sort(sort_li_effects).appendTo('.effects-list');
function sort_li_effects(a, b){
    return ($(a).data('sorte')) < ($(b).data('sorte')) ? 1 : -1;    
}
$(".effects-list li").filter( function(k, v) {
    if( k < 3 ) {
        min = parseInt($(v).data('sorte'));
        return false;
    } else
        return min > parseInt($(v).data('sorte'));
}).remove();

The problem I have is it sorts all of the list based on the first list. My question is how do I modify the script so it sorts all of the list on the page correctly?

Here is a jsFiddle with working code that shows the problem.

EDIT

To clarify a point. Lets say I have the following list:

<ul class="effects-list">
  <li data-sorte="2">creative</li>
  <li data-sorte="1">euphoric</li>
  <li data-sorte="2">uplifted</li>
  <li data-sorte="1">energetic</li>
  <li data-sorte="0">lazy</li>
  <li data-sorte="1">focused</li>
  <li data-sorte="1">happy</li>
  <li data-sorte="0">talkative</li>
  <li data-sorte="0">giggly</li>
  <li data-sorte="0">tingly</li>
  <li data-sorte="0">hungry</li>
  <li data-sorte="0">sleepy</li>
  <li data-sorte="0">aroused</li>
</ul>

I would want it to show creative, uplifted, euphoric, energetic, focused and happy as those are the top options by the numbers. euphoric, energetic, focused and happy are all tied at 1 thus I want to show them all. The original script does this.

3
  • loop over each effects-list and collect the li of that list instance only to sort. Commented Jun 23, 2014 at 2:20
  • What do you do with the 4th "2" if there are 4 "2"s ? Commented Jun 23, 2014 at 2:50
  • @bloodyKnuckles - It will show the top three numbers and if as you say they are 4 "2"s it will show all four values with 2 in it and nothing else. Make sense? Commented Jun 23, 2014 at 3:00

3 Answers 3

5

I slightly modified your script.

$('*[data-sorte="0"]').remove();
$(".effects-list").each(function() {
    var $list = $(this),
        $items = $list.find('li'),
        sortes = [];

    $items.detach().sort(sort_li_effects).filter(function(i) {
        var sorte = $(this).data('sorte');
        if (i < 3) {
            sortes.push(sorte);
            return true;
        }

        return sortes.indexOf(sorte) >= 0;
    }).appendTo($list);
});

function sort_li_effects(a, b) {
    return ($(a).data('sorte')) < ($(b).data('sorte')) ? 1 : -1;
}

http://jsfiddle.net/KK2bV/5/ or http://jsfiddle.net/KK2bV/6/ or http://jsfiddle.net/KK2bV/3/

Major differences:

  • It goes through li in every list and sorts correctly
  • It removes all unnecessary items at once using li:gt(2)
Sign up to request clarification or add additional context in comments.

8 Comments

I ran into an issue when I tried to implement the script. The problem is my original script would show more than three items IF there were ties in the numbers. In other words data-sorte in the li would have values of 2, 2, 1, 1, 1. I would want to show all of thoseli elements because they are the top options even though there is a tie. Does that make sense?
@Lynda: so what are the criterias then? Why it's not 2 2 1? Would it change anything if it was 2 2 2?
I tried to clarify in my edit to my question. If there was 2 2 2 it would show only those, however, if there is 2 2 1 1 1 it would show all of them. Another example: we have 4 3 2 2 2 1 1 1 I would want 4 3 2 2 2 to show.
@Jack: it does work properly according to the OP explanation. For the 4 4 2 2 2 1 1 the expected result is 4 4 2 2 2, that is the top 3 records including ties for the least values.
@zerkms Ahhh, with that being the interpretation you're absolutely right :)
|
2

You can do this in the following three steps:

$('.effects-list').replaceWith(function() {
  // step 1: grab list of items, remove all zero values and sort descending
  var $items = $(this).children()
    .filter(function() {
      return $(this).data('sorte') !== 0;
    }).sort(function(a, b) {
      var a_value = $(a).data('sorte'),
      b_value = $(b).data('sorte');

      if (a_value != b_value) {
        return a_value > b_value ? -1 : 1;
      }
      return 0;
    }),
  current,
  levels = 0,
  index = 0;

  // step 2: work out the top three
  while (index < $items.length && levels < 3) {
    var value = $items.eq(index).data('sorte');
    if (current === null || current != value) {
      current = value;
      ++levels;
    }
    ++index;
  }

  // step 3: replace the contents      
  return $items.slice(0, index);
});

See also: .replaceWith()

Demo

4 Comments

One problem, my original script would show more than three items IF there were ties in the numbers. In other words data-sorte in the li would have values of 2, 2, 1, 1, 1. I would want to show all of thoseli elements because they are the top options even though there is a tie. Does that make sense?
Using $(this).html(); shows all li elements vs the top three (including the ties).
@Lynda I mean $(this).html(items);.
Got it. => It shows all li elements with a number.
0

I don't like jQuery, however I can provide a javascript solution. I can recommend that you structure your HTML so that each UL has an ID that is enumerable. So:

 <ul class="effects-list" id="list1"> ... </ul>
 <ul class="...-list" id="list2">...<ul>

And so on. Then use a for loop to go through all the lists like this. Assume that there are 10 lists:

 for (var i = 0; i < 10; i++) {
      var list = document.getElementById("list"+i);
 // Then run your jQuery code on the list 10 times.
 }

Does that help?

1 Comment

I would avoid asking people not to down vote an answer. To me it is okay to post a non-jQuery solution as long as it solves the issue and the OP doesn't specify they are looking for a jQuery only solution.

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.