Flyingcows00
Flyingcows00

Reputation: 223

Jquery .next() not working as expected

On my website, I have an unordered list that is originally unpopulated. After the page loads, I use jquery and ajax to call a php page that loads data in from a database. It then returns that data to the ajax call so that it can create a bunch of list items and append them to the unordered list.

Each of these list items can be selected. When they are selected, I append a class to them called "selected-li" which just underlines the text. I also have arrows to navigate between the list items (i.e. up-arrow and down-arrow). I thought that the following would work...

$("#down-arrow").click(function(){
    $(".selected-li").next().addClass("selected-li");
});

...and it does, just not as expected. I have to click the down arrow twice in order for the class to be added to the next item. For some reason, it thinks that there is an invisible list item in between each of the ones displayed.

As a fix, I did the following:

$("#down-arrow").click(function(){
    $(".selected-li").next().next().addClass("selected-li");
});

It works now, but why does this happen? Why does it think that there is an extra li in there?

HTML code:

<div id="up-down-arrows">
    <img id="up-arrow" height="35px" width="35px" src="/../images/circle_arrow_up.png"></img><br><br><br>
    <img id="down-arrow" height="35px" width="35px" src="/../images/circle_arrow_down.png"></img>
</div>
<div id="article-list"><ul id="unordered-list"></ul></div>

Javascript code on return from ajax call:

function(data){
    for(var i = 0; i < data.length; i++){
        title = data[i]["name"];
        $("#unordered-list").append('<li title="' + title + '">' + title + '</li><br>');
    }
}

Upvotes: 2

Views: 1170

Answers (2)

Roko C. Buljan
Roko C. Buljan

Reputation: 206525

LIVE DEMO

.next() or no .next()... The <ul> tag is not supposed to hold <br> but list tag <li>.

Additionally I would suggest going like: This will also loop the selected LI element on buttons click.

var $ul = $('#unordered-list');
var liData = ""; // Popoulate string and append only once to UL (see below)
var $li; // Reference to future created LI
var liN; // Will hold the number of LI after creation
var sel = 0; // Selected index

$.ajax({
  dataType: "json",
  url: 'yourFile.json',
  success : function(data){
    for(var i = 0; i < data.length; i++){
      title = data[i].name;
      liData += '<li title="' + title + '">' + title + '</li>'; // <br>? c'mon..
    }
    $ul.append( liData ); // Append only once (performance matters!)
    $li = $('li', $ul);   // Find appended LI - put in collection
    liN = $li.length;     // How many?
    $li.eq(sel).addClass('selected-li'); // (add class to first)
  }  
}); 

$('#up-arrow, #down-arrow').click(function(){
  sel = (this.id.match('down') ? ++sel : --sel) % liN ;
  $li.removeClass('selected-li').eq(sel).addClass('selected-li');
});

Upvotes: 2

John S
John S

Reputation: 21492

It's the <br> tag. The .next() function gets the next sibling element, not the next <li> element. Besides it's not valid html to have a <br> between <li> elements.

Even if you find the reason why you have to call .next() twice, is this really going to do what you want? There could be multiple items with the "selected-li" class, and your code will then add that class to the items that are after each of them. That is, if items 3 & 7 are selected, Items 4 & 8 will also be selected after the down button is clicked. Here's a jsfiddle showing this.

Upvotes: 3

Related Questions