Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery slice negative index not working

I got a weird problem, probably I am missing something here.

I got a list of elements, one part of it is visible, the other is invisible.

I want to select the last 3 elements of the invisible part. I added a snipped to illustrate the issue.

The result I am looking for is for 10, 11, 12 to be shown after the js ran, not 1,2,3 I thought slice(-3) would give me the last 3 elements of the array, but it seems I am missing something. Same problem happens when I am using filter(':gt(-4)'). Can someone explain me what I am doing wrong?

jQuery(document).ready(function() {
  setTimeout(function () {
    var prevs = jQuery('li').filter(':visible').first().prevAll();
    var vis = jQuery('li').filter(':visible');
    
    vis.hide(1000);
    prevs.slice(-3).show(1000);
    
  }, 1000);
});
li:nth-last-child(n+4) {
  display: none
}

li {
  width: 30px;
  height: 30px;
  border: 1px dotted gray;
  background-color: red;
  list-style: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
</ul>
like image 932
user3154108 Avatar asked Feb 17 '26 15:02

user3154108


1 Answers

The problem is var prevs = jQuery('li').filter(':visible').first().prevAll();, specifically, prevAll(). Per jquery documentation:

The .prevAll() method searches through the predecessors of these elements in the DOM tree and construct a new jQuery object from the matching elements; the elements are returned in order beginning with the closest sibling.

The array you get back are elements 0-11, but they are in the reverse order. So prevs[0] == 12. The last 3 elements are now 1, 2, and 3. To fix this, you need to reverse the array. Just wrap that right hand statement inside of Array.prototype.reverse.call(). Here is what you want I believe

jQuery(document).ready(function() {
  setTimeout(function () {
    var prevs = Array.prototype.reverse.call(jQuery('li').filter(':visible').first().prevAll());
    var vis = jQuery('li').filter(':visible');
    
    vis.hide(1000);
    prevs.slice(-3).show(1000);
    
  }, 1000);
});
li:nth-last-child(n+4) {
  display: none
}

li {
  width: 30px;
  height: 30px;
  border: 1px dotted gray;
  background-color: red;
  list-style: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
</ul>
like image 179
Nick G Avatar answered Feb 19 '26 03:02

Nick G



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!