Reputation: 43
I am trying to write some sorting code. I would like to sort a list like:
and turn into:
<html>
<head>
<title>Sort list items alphabetically with Javascript</title>
<script type="text/javascript">
function sortUnorderedList(ul, sortDescending) {
if(typeof ul == "string")
ul = document.getElementById(ul);
var lis = ul.getElementsByTagName("LI");
var vals = [];
for(var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i].innerHTML);
vals.sort();
if(sortDescending)
vals.reverse();
for(var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i];
}
window.onload = function() {
var desc = false;
document.getElementById("test").onclick = function() {
sortUnorderedList("list", desc);
desc = !desc;
return false;
}
}
</script>
</head>
<body>
<input type="button" id="test" value="Sort List (click again to reverse)"/>
<ul id="list">
<li>banana</li>
<li>cake</li>
<ul>
<li>egg</li>
<li>doughnut</li>
<li>burger</li>
</ul>
<li>rice</li>
<li>apple</li>
</ul>
</body>
</html>
Upvotes: 4
Views: 163
Reputation: 337560
The main issue with your code is that your HTML is invalid; ul
cannot be a child of another ul
. Only li
or ol
can. This invalid HTML causes the li
to be rendered differently than you expect so the sorting is affected. To fix this correct the HTML so the nested 'cake' ul
is within the li
.
As you've tagged the question with jQuery, here's a much simple implementation of what you originally had:
jQuery($ => {
let $ul = $('#list');
$('#test').on('click', function() {
let sort = $(this).data('sortasc');
let dir = sort ? [1, -1] : [-1, 1];
$ul.children('li').sort((a, b) => a.innerText.trim() < b.innerText.trim() ? dir[0] : dir[1]).appendTo($ul);
$(this).data('sortasc', !sort);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="test">Toggle sort</button>
<ul id="list">
<li>banana</li>
<li>
cake
<ul>
<li>egg</li>
<li>doughnut</li>
<li>burger</li>
</ul>
</li>
<li>rice</li>
<li>apple</li>
</ul>
Upvotes: 3