I'm wondering what is the most efficient way of inserting an item (in this case, a string), into its correct alphabetical order, with ONLY JavaScript (not jQuery)? I thought that by sorting the list straight after inserting the item would be sufficient, but doesn't work. I am getting the value to be inserted via a value entered into a textfield.
Before inserting the new item, the list looks like:
- Albatross
- Fantail
- Kea
- Kiwi
- Takahe
- Tui
If I choose to add "Bellbird" to this list, I would expect the list to now look like:
- Albatross
- Bellbird
- Fantail
- Kea
- Kiwi
- Takahe
- Tui
Here is the code I am using to try and achieve the desired oute:
HTML:
<ul id="birds">
<li>Albatross</li>
<li>Fantail</li>
<li>Kea</li>
<li>Kiwi</li>
<li>Takahe</li>
<li>Tui</li>
</ul>
<p><label for="addNewBirdField">Add new bird: </label>
<input type="text" id="addNewBirdField" /></p>
<p><button id ="addItem">Add new bird</button></p>
JavaScript:
function addNewBird()
{
var birdList = document.getElementById("birds"); //get birds unordered list
var newBirdItem = document.createElement("li"); // create new li element
var bird = document.getElementById("addNewBirdField").value // get data from form field
var birdValue = document.createTextNode(bird); // create new textNode with value from previous step
newBirdItem.appendChild(birdValue); // append textNode from previous step to li element (newBirdItem)
birdList.appendChild(newBirdItem); // append li element to bird list
birdList.sort();
}
var addItem = document.getElementById("addItem");
addItem.onclick = addNewBird;
I've looked at this link at sorting arrays (I am assuming with my knowledge on programming that each list element is in an array). I understand what lexicographically sorting is - I learned this earlier this week.
If anyone can help me out on this one would be very grateful.
I'm wondering what is the most efficient way of inserting an item (in this case, a string), into its correct alphabetical order, with ONLY JavaScript (not jQuery)? I thought that by sorting the list straight after inserting the item would be sufficient, but doesn't work. I am getting the value to be inserted via a value entered into a textfield.
Before inserting the new item, the list looks like:
- Albatross
- Fantail
- Kea
- Kiwi
- Takahe
- Tui
If I choose to add "Bellbird" to this list, I would expect the list to now look like:
- Albatross
- Bellbird
- Fantail
- Kea
- Kiwi
- Takahe
- Tui
Here is the code I am using to try and achieve the desired oute:
HTML:
<ul id="birds">
<li>Albatross</li>
<li>Fantail</li>
<li>Kea</li>
<li>Kiwi</li>
<li>Takahe</li>
<li>Tui</li>
</ul>
<p><label for="addNewBirdField">Add new bird: </label>
<input type="text" id="addNewBirdField" /></p>
<p><button id ="addItem">Add new bird</button></p>
JavaScript:
function addNewBird()
{
var birdList = document.getElementById("birds"); //get birds unordered list
var newBirdItem = document.createElement("li"); // create new li element
var bird = document.getElementById("addNewBirdField").value // get data from form field
var birdValue = document.createTextNode(bird); // create new textNode with value from previous step
newBirdItem.appendChild(birdValue); // append textNode from previous step to li element (newBirdItem)
birdList.appendChild(newBirdItem); // append li element to bird list
birdList.sort();
}
var addItem = document.getElementById("addItem");
addItem.onclick = addNewBird;
I've looked at this link at sorting arrays (I am assuming with my knowledge on programming that each list element is in an array). I understand what lexicographically sorting is - I learned this earlier this week.
If anyone can help me out on this one would be very grateful.
Share Improve this question edited Sep 22, 2012 at 10:09 alex 490k204 gold badges889 silver badges991 bronze badges asked Sep 22, 2012 at 9:52 RobRob 1,2806 gold badges25 silver badges36 bronze badges 1- Well from my point, sort() would work fine but calling sort on birdList (which is not an array, but a ul DOM element) wouldn't make sense. Get all the li elements and sort them – OJay Commented Sep 22, 2012 at 9:57
2 Answers
Reset to default 8birdList.sort();
This will not work, as the value returned by document.getElementById()
is never an Array
, it's either a reference to an element or null
if the element wasn't found. Only Array
s (by default) have a sort()
method.
Instead, what you want is...
var birds = birdList.getElementsByTagName("li");
birds = Array.prototype.slice.call(birds).sort(function(a, b) {
return a.firstChild.data.toLowerCase().localeCompare(b.firstChild.data.toLowerCase());
});
for (var i = 0, length = birds.length; i < length; i++) {
birdList.appendChild(birds[i]);
}
jsFiddle.
If you didn't need to support older browsers...
var birds = birdList.querySelectorAll("li");
birds = Array.prototype.slice.call(birds).sort(function(a, b) {
return a.textContent.toLowerCase().localeCompare(b.textContent.toLowerCase());
}).forEach(function(bird) {
birdList.appendChild(bird);
});
jsFiddle.
Finally, if you did have jQuery at your disposal...
$(birdList).find("li").sort(function(a, b) {
return $(a).text().toLowerCase().localeCompare($(b).text().toLowerCase());
}).each(function() {
$(birdList).append(this);
});
jsFiddle.
You don't have to re-sort the entire list, and reinsert every item.
You could just find the position in the sorted list to insert the new item.
<!doctype html>
<html lang="en">
<head>
<meta charset= "utf-8">
<title>Test Page</title>
<script>
function addNewBird(){
var bird= document.getElementById("addNewBirdField").value;
if(bird){
bird= bird.charAt(0).toUpperCase()+ bird.substring(1).toLowerCase();
var birdList= document.getElementById("birds"),
list= birdList.getElementsByTagName('li'),
i= 0, who= list[0],
newBirdItem= document.createElement("li");
newBirdItem.appendChild(document.createTextNode(bird));
while(who && who.innerHTML<bird) who= list[++i];
if(who) birdList.insertBefore(newBirdItem, who);
else birdList.appendChild(newBirdItem);
}
return newBirdItem;
}
</script>
</head>
<body>
<div>
<ul id="birds">
<li>Albatross</li>
<li>Fantail</li>
<li>Kea</li>
<li>Kiwi</li>
<li>Takahe</li>
<li>Tui</li>
</ul>
<p><label for="addNewBirdField">Add new bird: </label>
<input type="text" id="addNewBirdField" /></p>
<p><button id ="addItem" onclick="addNewBird()">Add new bird</button></p>
</div>
</body>
</html>