0

I have a bootstrap navigation bar as below on which I have dropdown menu.

<nav class="navbar navbar-inverse">
  <div class="container-fluid">
    <div class="navbar-header">
       <a class="navbar-brand" href="#">WebSiteName</a>
    </div>
    <div class="collapse navbar-collapse" >
      <ul id="my-navbar-ul" class="nav navbar-nav">

      </ul>
    </div>
</div>

I am appending elements to the dropdown menu at a later point of time and want them to be displayed in sorted manner. Below is my code :

$mynavbarul = $('#my-navbar-ul');

$mynavbarul.append('<li class= "dropdown">
                    <a rel="nofollow" href="#" class = "dropdown-toggle" data-toggle= "dropdown" role="button"  id = "namelist">Select a Name<span class ="caret"></span></a>
                    <ul class="dropdown-menu" role="menu">
                    <li><a rel="nofollow" href="#" id="mark">Mark</a><li>
                    <li><a rel="nofollow" href="#" id="allan">Allan</a><li>
                    <li><a rel="nofollow" href="#" id="derek">Derek</a><li>
                    <li><a rel="nofollow" href="#" id="brian">BRIAN</a><li>
                    </ul>
                  </li>' );

The names in the list could be in lower or upper case both. I have tried the following sorting function and calling it explicitly from the .js file where above code is written. However, the sorting mechanism seems to be not working and getting stuck somewhere in between the function. I have put debug statement to print the selectedValue and it is coming as blank. I must be doing something wrong. Below is my function :

function sortDropDownListByText() {
    // Loop for each select element on the page.
    $("#namelist").each(function() {

        // Keep track of the selected option.
        var selectedValue = $(this).val();
        console.log("selected value = "+selectedValue); //coming as blank

        // Sort all the options by text. I could easily sort these by val.
        $(this).html($("option", $(this)).sort(function(a, b) {
            return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
        }));

        // Select one option.
        $(this).val(selectedValue);
    });
}

Any help to get it work would be much appreciated. Thanks.

2
  • console.log comes blank or doesn't come at all? Commented Oct 3, 2017 at 7:49
  • @Jurij Jazdanov It is coming as it is printing "selected value = " , but the value after = is missing. Commented Oct 3, 2017 at 9:35

3 Answers 3

1

If this is only about sorting the items then maybe this is a possibility.

(I assume the list items should have a closing tag)

<li><a rel="nofollow" href="#" id="mark">Mark</a></li> 

instead of

<li><a rel="nofollow" href="#" id="mark">Mark</a><li>

What you could do is get the ul id="my-navbar-ul" instead of id of the a id = "namelist".

Then you can find the list items in the <ul> and store them. Remove the list items from the <ul> and sort the ones that you have stored. Loop the stored ones and append them back to the <ul>.

Example:

$mynavbarul = $('#my-navbar-ul');

            var html = '<li class= "dropdown">';
            html += '<a rel="nofollow" href="#" class = "dropdown-toggle" data-toggle= "dropdown" role="button"  id = "namelist">Select a Name<span class ="caret"></span></a>';
            html += '<ul class="dropdown-menu" role="menu">';
            html += '<li><a rel="nofollow" href="#" id="mark">Mark</a></li>';
            html += '<li><a rel="nofollow" href="#" id="allan">Allan</a></li>';
            html += '<li><a rel="nofollow" href="#" id="derek">Derek</a></li>';
            html += '<li><a rel="nofollow" href="#" id="brian">BRIAN</a></li>';
            html += '</ul>';
            html += '</li>';
            $mynavbarul.append(html);

            function sortDropDownListByText() {
                var ul = $("#my-navbar-ul ul.dropdown-menu");
                var listItems = ul.find("li");
                ul.empty();
                listItems.sort(function (a, b) {
                    return $(a).children('a').first().html() < $(b).children('a').first().html() ? -1 : 1;
                }).each(function (index, value) {
                    ul.append(value);
                });
            }

            sortDropDownListByText();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">WebSiteName</a>
        </div>
        <div class="collapse navbar-collapse">
            <ul id="my-navbar-ul" class="nav navbar-nav">

            </ul>
        </div>
    </div>
</nav>

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your solution. It works absolutely fine, however there is a small problem. To keep things simple I did not mention it earlier. Likewise #namelist , the $mynavbarul actually contains another menu as 'Select a place' which contains a list of countries such as USA, ENG, France, India. With your solution, both the sorted dropdowns values are getting combined as 'Allan BRIAN, Derek, ENG, France, India, Mark, USA' . I tried to give an id to the dropdown-menu as '<ul class="dropdown-menu" role="menu" id="nameid>' and use it as ul.nameid , but it does not work.
I tried a solution and it worked. I used another unique class name along with dropdown-menu as <ul class="names-menu dropdown-menu" role="menu">'; Then using it as var ul = $("#my-navbar-ul ul.names-menu"); Similarly var ul = $("#my-navbar-ul ul.place-menu"); for 'Select a place'. It has worked. Please let me know if you have any better and elegant solution for this.
1

I would personally add the values to an array, sort the array with the built-in functions, and then create a loop which will go through all of the values in the array and create the list items.

This has been done a ton of times and I'm sure it's somewhere on Stack Overflow, too.

Comments

1

Using jQuery you could first move the html code to the html file using a script of type text/template and notice that the closing tag for li should be </li>.

Than, you can create a variable $list with the list of elements to sort, but at the same time you remove the elements from the DOM with $list = $mynavbarul.find('li ul.dropdown-menu').children('li').remove();.

Than, you do a sort with JavaScript.prototype.sort() and finally $dropdownMenu.append($list); to populate again the ul.dropdown-menu with the list of sorted elements all at once for performance.

Code:

var $mynavbarul = $('#my-navbar-ul'),
    $dropdownMenu = null,
    $list = null;

$mynavbarul.append($('#list').html());
$dropdownMenu = $('ul.dropdown-menu');

$list = $mynavbarul.find('li ul.dropdown-menu').children('li').remove();
$list.sort(function (a, b) {
  var aId = $(a).find('a').attr('id').toUpperCase(),
      bId = $(b).find('a').attr('id').toUpperCase();
  return aId > bId ? 1 : aId < bId ? -1 : 0;
});

$dropdownMenu.append($list);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navbar navbar-inverse">
  <div class="container-fluid">
    <div class="navbar-header">
       <a class="navbar-brand" href="#">WebSiteName</a>
    </div>
    <div class="collapse navbar-collapse" >
      <ul id="my-navbar-ul" class="nav navbar-nav"></ul>
    </div>
</div>

<script id="list" type="text/template">
<li class="dropdown">
  <a rel="nofollow" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" id="namelist">
    Select a Name<span class="caret"></span>
  </a>
  <ul class="dropdown-menu" role="menu">
    <li><a rel="nofollow" href="#" id="mark">Mark</a></li>
    <li><a rel="nofollow" href="#" id="allan">Allan</a></li>
    <li><a rel="nofollow" href="#" id="derek">Derek</a></li>
    <li><a rel="nofollow" href="#" id="brian">BRIAN</a></li>
  </ul>
</li>
</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.