Selectbox jquery selector problem

Hi

This is my first visit to Sitepoint, it looks a really helpful place :slight_smile:

I am learning how to javascript and jquery and figured best way to learn is by dealing with real life problems, so heres my first one.

To show you what iā€™ve done iā€™ve uploaded a test file here

http://www.harshadpatel.co.uk/selectbox/

As you can see i have done a page with two jump menus, as I cant style selects properly, Iā€™ve attempted to spit them out as liā€™s so i can style them so I have got up to this point, the problem i have is that the top menu it should only say 1, 2, 3 and the bottom one 4, 5, 6 at the moment it spits it out as 1,2,3,4,5,6 on both menus.

This is the html

<form name="join-us-home" class="join-us-home">    
    <select class="menu">
        <option value="value-1">1</option>
        <option value="value-2">2</option>
        <option value="value-3">3</option>
    </select>
    <input type="submit" value="Go" />
</form>


<form name="join-us-home" class="join-us-home">    
    <select class="menu">
        <option value="value-4">4</option>
        <option value="value-5">5</option>
        <option value="value-6">6</option>
    </select>
    <input type="submit" value="Go" />
</form>

and the JS is this

<script type="text/javascript">
    $(document).ready(function () {
        var list = $('<ul>');
        $('.menu option').each(function () {
            $('select').hide();
            var test = $(this).attr('value');
            var text = $(this).text();
            $('<li><a href="' + test + '">' + text + '</a></li>').appendTo(list);
        });
        list.insertBefore($('input'));

        $('.join-us-home').submit(function () {
            window.location = $('.menu', $(this)).val();
            return false;
        });
    });
</script>

i think the selector is wrong, but i am a bit stuck here, any pointers would be greatly appreciated :slight_smile:

Thanks again,

harshyp

Hi there,

And welcome to the forums!

I had a look at your code.
The problem is that you are creating your unordered list (with six list items), then you are inserting it twice (once before each input element).

Here are a couple of observations to your code:

[LIST]
[]var list = $('<ul>'); - here you are telling jQuery to get all of the <ul> tags it can find on the page. However, there are none.
[
]$('.menu option').each(function () { - here you are finding any elements with the class ā€˜menuā€™, getting a reference to each <option> tag contained within these element and attaching a function to it. This in itself is fine.
[]$('select').hide(); - however, for each <option> tag jQuery finds, it will now try and find all the <select> tags within the document and hide them. This should not be within the loop, as it only needs to be done once.
[
]list.insertBefore($('input')); - This is whatā€™s causing the list to display twice. jQuery is getting a reference to both input tags in the document (the two submit buttons) and inserting the list it has just created before them.
[/LIST]So, I rewrote yourcode a little. I gave each <select> element a unique id. Now, this should more or less do what you want:

<!DOCTYPE html>
  <html>
    <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <meta charset=utf-8 />
    <title>Sliderbox test</title>
  </head>

  <body>
    <form name="join-us-home" class="join-us-home">
      <select class="menu" id="first">
        <option value="value-1">1</option>
        <option value="value-2">2</option>
        <option value="value-3">3</option>
      </select>
      <input type="submit" value="Go" />
    </form>

    <form name="join-us-home" class="join-us-home">
      <select class="menu" id="second">
        <option value="value-4">4</option>
        <option value="value-5">5</option>
        <option value="value-6">6</option>
      </select>
      <input type="submit" value="Go" />
    </form>

    <script type="text/javascript">
      $(document).ready(function () {
        var list1 = "<ul>"
        $("#first option").each(function(){
          list1 += '<li><a href="' + this.value + '">' + this.text + '</a></li>';
        });
        list1 += "</ul>";
        $("#first").replaceWith(list1);

        // Rinse and repeat
        var list2 = "<ul>"
        $("#second option").each(function(){
          list2 += '<li><a href="' + this.value + '">' + this.text + '</a></li>';
        });
        list2 += "</ul>";
        $("#second").replaceWith(list2);
      });
    </script>
  </body>
</html> 

My only remaining question is: is there any reason you didnā€™t use list items in the first place?
Iā€™m not sure how you are intending to submit your form with this approach.

Nonetheless, I hope this helps you.
If you have any questions, just let me know.

Hello Pullo many thanks for your reply, Iā€™ve learned some new things there such as replaceWith didnt know you could that, many thanks for showing me this :slight_smile: yes thats what i wanted to do, idā€™s crossed my mind however i thought as it was a separate item it would do everything that was in that select but this isnt the case, in terms of the purpose there are some sites I am building in the future use jump menus to navigate parts of the site, so its going to work as a jump menu but using liā€™s to get better styling, the user selects an item from the drop down and then presses ā€œGoā€ to navigate to that page :slight_smile: thanks for your help I am i think 50% there, I am gonna try this weekend to implement the other half :slight_smile:

Hi Pullo finally got round to adding some more script to make the jumpmenu work correctly, its now looking like this http://www.harshadpatel.co.uk/selectbox/ and its now working correctly, many thanks for your help Pullo in helping me with this :), the next thing i want to do is make it more modular so it can be dropped easily into any pagee and I am going to try and turn this into a plugin as i havent done one and is something i need to learn :slight_smile: Just one question if i want to use classes instead of idā€™s to seperate the menu items is this possible?

Iā€™ve got a lot to learn but i think i am making some progress :slight_smile:

Hi,

Nice one! Iā€™m glad youā€™ve got things working.

Sure. You would do this:

var sel = $(".menu")

This gives you an array of items wit the class menu. You can then iterate over them like this:

sel.each(function(){console.log(this);})

Does that help?

Hello Pullo many thanks for your reply, Iā€™ll definitely give it a try and post back :slight_smile:

Hello Pullo

I had some upload issues yesterday, Iā€™ve given your code a try I must have done it wrong as its now undefining

			var sel = $(".menu")
            var list1 = "<ul class='firstmenu'><li><span class='intro'>Please select from the dropdown menu below</span><ul id='list-one'>"
			//sel.each(function(){console.log(this);})
            sel.each(function () {
               list1 += '<li><a href="' + this.value + '">' + this.text + '</a></li>';
            });
            list1 += "</ul></li></ul>";
            $(sel).replaceWith(list1);

i forgot to say iā€™ve uploaded it as well. http://www.harshadpatel.co.uk/selectbox/

Hi there harshyp,

Yeah, the problem with your code is that this:

var sel = $(".menu")

returns an array of items with the class ā€œmenuā€.

And when you iterate over them like so:

sel.each(function(){ ... do some stuff ...})

this will reference a <select> element, not the <option> elements contained within it.

So, doing this:

list1 += '<li><a href="' + this.value + '">' + this.text + '</a></li>';

will of course return undefined, as the <select> element, doesnā€™t have a value attribute or text() method.

So what you should do within the function passed to each, is to get all of the children of the select element (the <option> elements), so that you can manipulate them in some way.
You can do this with the map() function, like this:

$(this).children().map(function() {
  list1 += '<li><a href="' + $(this).val() + '">' + $(this).text() + '</a></li>';
}).get();

Here is a complete example for you to have a play around with:

<!DOCTYPE html>
  <html>
    <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <meta charset=utf-8 />
    <title>Sliderbox test</title>
    <style type="text/css">
        form ul {float: left;}
        form ul, li {list-style: none; margin: 0; padding: 0;}
        form li span.intro {background-color: #000; border-bottom: #fff 1px solid; color: #fff; padding: 10px; display: block; width: 300px;}
        form li span.intro:hover {cursor: both;}
        form p {display: block; width: 200px; padding: 5px 0; margin: 0; background-color: #ccc; border-bottom: #000 1px solid;}
        form ul li a {width: 300px; padding: 5px 0; background-color: #ccc; border-bottom: #000 1px solid; display: block; padding: 10px;}
        form ul li ul {display: none;}
        form ul li:hover ul {display: block;}
        .no-display {display: none;}
        input[type="submit"]{ float: left;}
    </style>
  </head>
 
  <body>
    <form id="join-us-homey">    
      <select class="menu" id="first">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select>
      <input type="submit" value="Go" />
    </form>
    
    <script type="text/javascript">
      $(document).ready(function () {
        var sel = $(".menu")
        var list1 = "<ul class='firstmenu'><li><span class='intro'>Please select from the dropdown menu below</span><ul id='list-one'>"
        sel.each(function () {
          $(this).children().map(function() {
            list1 += '<li><a href="' + $(this).val() + '">' + $(this).text() + '</a></li>';
          }).get();
        });
        list1 += "</ul></li></ul>";
        $(sel).replaceWith(list1);
      });
    </script>
  </body>
</html>

Aah yes it makes sense now because when i did a console.log with your code it pinpointed the options, then when i did it only picked out the select value, its something i need to look into traversing the dom using Javascript, many thanks for showing me this :slight_smile: