sigmaxf
sigmaxf

Reputation: 8482

Insert <li> element in a list's specific position respecting data-order attribute

I have a list with a numbered data-order attribute. This attribute isn't necessarily in a sequence like 1,2,3,4... but instead it's in a growing number sequence without a determined increase, something like 8,30,201,380.

What I want to do is insert an element in this list using jquery, respecting the order, so, if the data-order of the new element is 58, it would go between 30 and 201...

Since the elements are not in a set incremental sequence, a simple find and insert woudn't work, any ideas on how I can achieve this without wasting too much processing?

Upvotes: 1

Views: 1255

Answers (2)

Roamer-1888
Roamer-1888

Reputation: 19288

Assume ...

  • $ul is the list node (jQuery-wrapped)
  • $li is the list item to be inserted (jQuery-wrapped)
var o = $li.appendTo($ul).data('order');//initially, append $li to end of the list, and read its order attribute.
$ul.find("li").each(function() {
    if(o < $(this).data('order')) {
        $li.insertBefore(this); //if $li's order` is less than current item's order, then move $li above current item.
        return false; //break
    }
});

If, during the scan, the o < $(this).data('order') condition is not met, then the new list item will remain at the end of the list.

DEMO

Upvotes: 2

Gabriele Petrioli
Gabriele Petrioli

Reputation: 195982

When querying the DOM (with jQuery methods) you get back elements in the sequence they appear in the DOM.

So filtering your elements and then inserting after the last item with a value smaller than the new one..

  var newElementOrder = 10 // dummy value;

  var all = $('li[data-order]'),
      less = all.filter(function() {
          return +$(this).data('order') < newElementOrder;
      });

  if (less.length) {
    less.last().after(newElement);
  } else {
    all.first().before(newElement);
  }

Full Demo

$('.add').on('click', function() {
  var newElementOrder = +$('.add-value').val(),
    newElement = $('<li data-order="' + newElementOrder + '">Item with order #' + newElementOrder + '</li>');

  var all = $('li[data-order]'),
    less = all.filter(function() {
      return +$(this).data('order') < newElementOrder;
    });

  if (less.length) {
    less.last().after(newElement);
  } else {
    all.first().before(newElement);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<ul>
  <li data-order="8">Item with order #8</li>
  <li data-order="30">Item with order #30</li>
  <li data-order="201">Item with order #201</li>
  <li data-order="380">Item with order #380</li>
</ul>

<button class="add">add after</button>
<input type="text" class="add-value" />

Upvotes: 1

Related Questions