8

How do I convert a dropdown in this format:

<select id="yearfilter" name="yearfilter">
<option value="">All years</option>
<option value="2011">2011</option>
<option value="2010">2010</option>
<option value="2009">2009</option>
</select>

into an unordered list in this format:

<ul id="yearfilter" name="yearfilter">
<li value="">All years</li>
<li value="2011">2011</li>
<li value="2010">2010</li>
<li value="2009">2009</li>
</ul>

using jquery??

6 Answers 6

14
$('#yearfilter').parent().append('<ul id="newyearfilter" name="yearfilter"></ul>');
$('#yearfilter option').each(function(){
  $('#newyearfilter').append('<li value="' + $(this).val() + '">'+$(this).text()+'</li>');
});
$('#yearfilter').remove();
$('#newyearfilter').attr('id', 'yearfilter');

this is how I would do it.

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

Comments

13

I am so going to get some hate for this solution but what about this?

var rep = $("select")
          .clone()
          .wrap("<div></div>")
          .parent().html()
          .replace(/select/g,"ul")
          .replace(/option/g,"li");

$("select").replaceWith(rep);

Edit:

And almost five years later; yes, I hate myself for this answer.

There are a few problems here. What if you have an option in the list that goes like this: <option value="5">With optional engraving</option>. You'll get <li value="5">Withlialengraving</li>. Here's an alternative in vanilla javascript (because jQuery doesn't really support this).

var parent = document.querySelector('select'),
    docFrag = document.createDocumentFragment(),
    list = document.createElement('ul');

// build list items
while(parent.firstChild) {
  // we simultaniously remove and store the node
  var option = parent.removeChild(parent.firstChild);

  // not interested in text nodes at this point
  if(option.nodeType !== 1) continue;

  // lets build a list item
  var listItem = document.createElement('li');

  // we loop through the properties of the node and
  // apply only the ones that also exist as atributes
  for(var i in option) {
    if(option.hasAttribute(i)) listItem.setAttribute(i, option.getAttribute(i));
  }

  // loop through the select children to append to the
  // list item.  We want text nodes this time.
  while(option.firstChild) {
    listItem.appendChild(option.firstChild);
  }

  // append them to the document fragment for easier
  // appending later
  docFrag.appendChild(listItem);
}

// build wrapping ul.  Same as above
for(var i in parent) {
  if(parent.hasAttribute(i)) list.setAttribute(i, parent.getAttribute(i));
}

// add the list items to the list
list.appendChild(docFrag);

// lastly replace the select node with the list
parent.parentNode.replaceChild(list, parent);
<select id="yearfilter" name="yearfilter">
<option value="">All years</option>
<option value="2011">2011</option>
<option value="2010">2010</option>
<option value="2009">2009</option>
</select>

1 Comment

what a simple solution perfect
2

You can use map() to build the <li> elements from the <option> elements, and replaceAll() to replace the <select> element:

var $yearFilter = $("#yearfilter");
$yearFilter.find("option").map(function() {
    var $this = $(this);
    return $("<li>").attr("value", $this.attr("value")).text($this.text()).get();
}).appendTo($("<ul>").attr({
    id: $yearFilter.attr("id"),
    name: $yearFilter.attr("name")
})).parent().replaceAll($yearFilter);

You can see the results in this fiddle.

1 Comment

this should be the correct answer. All of the others assume perfect input
1

There is no reason to add name attributes to ul, nor value attributes to li tags.

Try this: http://jsfiddle.net/vfjFK/2/

$(function(){
    var id = "yearfilter";
    $('#'+id).after("<ul id='temp' />")
        .children("option").each(function() {
            $("#temp").append("<li>"+$(this).text()+"</li>");
        })
        .end().remove();
    $('#temp').attr("id",id);
});

If you really need the useless attributes, though, try this: http://jsfiddle.net/vfjFK/3/

$(function(){
    var id = "yearfilter";
    $('#'+id).after("<ul id='temp' />")
        .children("option").each(function() {
            $("#temp").append('<li value="'+$(this).val()+'">'+$(this).text()+"</li>");
        })
        .end().remove();
            $('#temp').attr({"id":id,"name":id});
});

Comments

0

Here is one way to do it:

var $select = $('#yourSelectElement'),
    $ul = $('<ul></ul>').attr('id', $select.attr('id'))
                        .attr('name', $select.attr('name'));

$select.children().each(function() {
    var $option = $(this);
    $('<li></li>').val($option.val())
                  .text($option.text())
                  .appendTo($ul);
});

$select.replaceWith($ul);

Comments

0

You would simply replace the tags with their counterpart:

 var select = $('#yearFilter');
 var ul = $('<ul/>');
 ul.attr({ id: select.attr('id'), name: select.attr('name') });

 select.find('option').each(function()
 {
     var item = $('<li/>');
     item.text(this.Text).val(this.val());

     ul.append(item);
 });

 $('#yearFilter').replaceWith(ul);

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.