0

I was wondering what is the best way to convert select menu into buttons with an initial selected state.

I searched for this solution on Stackoverflow and this is the only link I found close enough. However, there's an error in the code making all items initially selected, when only one item with the "selected" attribute should be highlighted. Original Stackoverflow Post

$(function() {
  $("select option").unwrap().each(function() {
    var btn = $('<div class="btn">' + $(this).text() + '</div>');
    if ($(this).is(':checked')) btn.addClass('on');
    $(this).replaceWith(btn);
  });


  $(document).on('click', '.btn', function() {
    $('.btn').removeClass('on');
    $(this).addClass('on');
  });
});
div.btn {
  display: inline-block;
  /** other styles **/
}

div.btn.on {
  background-color: #777;
  color: white;
  /** styles as needed for on state **/
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="text">
     <option selected>Yes</option>
     <option>No</option>
    </select>
Gerard
  • 15,418
  • 5
  • 30
  • 52

4 Answers4

2

If you want to check if an <option> element has the attribute of selected, you can simply do it the native JS way by using Elements.hasAttribute() on the DOM node, i.e.:

this.hasAttribute('selected')

If you want to use jQuery anyway, that is still possible, but a little too verbose for my liking:

  • $(this).is('[selected]'): simply checks if the element has the attribute selected using the attribute selector [...]
  • $(this).attr('selected') will return a true/false boolean if the selected attribute is specified. See next solution if you want a super verbose one. Technically speaking, selected is a boolean attribute so this check is—more often that not—sufficient
  • $(this).attr('selected') !== false && typeof $(this).attr('selected') !== 'undefined': see explanation here.

$(function() {
  $("select option").unwrap().each(function() {
    var btn = $('<div class="btn">' + $(this).text() + '</div>');
    if (this.hasAttribute('selected')) btn.addClass('on');
    $(this).replaceWith(btn);
  });


  $(document).on('click', '.btn', function() {
    $('.btn').removeClass('on');
    $(this).addClass('on');
  });
});
div.btn {
  display: inline-block;
  /** other styles **/
}

div.btn.on {
  background-color: #777;
  color: white;
  /** styles as needed for on state **/
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="text">
  <option selected>Yes</option>
  <option>No</option>
</select>
Terry
  • 63,248
  • 15
  • 96
  • 118
0

You need to check the value for attribute 'selected' instead of 'checked'.

$(function() {
  $("select option").unwrap().each(function() {
    var btn = $('<div class="btn">' + $(this).text() + '</div>');
    if ($(this).attr('selected') == 'selected') btn.addClass('on');
    $(this).replaceWith(btn);
  });


  $(document).on('click', '.btn', function() {
    $('.btn').removeClass('on');
    $(this).addClass('on');
  });
});
div.btn {
  display: inline-block;
  /** other styles **/
}

div.btn.on {
  background-color: #777;
  color: white;
  /** styles as needed for on state **/
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="text">
     <option selected>Yes</option>
     <option>No</option>
    </select>
Gerard
  • 15,418
  • 5
  • 30
  • 52
  • `selected` is a boolean attribute, and it does not need to have any value. Simply checking of `$(this).attr('selected')` (which evaluates to true/false) will be sufficient :) – Terry Aug 10 '17 at 06:30
0

Just replace below line into your code.

if ($(this).attr('selected')) btn.addClass('on');

your code : if ($(this).is(':checked')) btn.addClass('on');

replaced code : if ($(this).attr('selected')) btn.addClass('on');

$(function() {
  $("select option").unwrap().each(function() {
    var btn = $('<div class="btn">' + $(this).text() + '</div>');
    if ($(this).attr('selected')) btn.addClass('on');
    $(this).replaceWith(btn);
  });


  $(document).on('click', '.btn', function() {
    $('.btn').removeClass('on');
    $(this).addClass('on');
  });
});
div.btn {
  display: inline-block;
  /** other styles **/
}

div.btn.on {
  background-color: #777;
  color: white;
  /** styles as needed for on state **/
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="text">
     <option selected>Yes</option>
     <option>No</option>
    </select>
0

The reason they are all selected is that, as they are replaced, the next one becomes selected. Additionally, when you unwrap the 'select' it is removed from the form, and as such, will not submit with post data. I created a JS Fiddle to correct both of these issues, as well as update ALL of the select combos so that they work independently.

CSS Code:

div.btn {
  display: inline-block;
  border: 2px solid #ccc;
  margin-right: 5px;
  padding: 2px 5px;
  cursor: pointer;
}

div.btn.on {
  background-color: #777;
  color: white;
}

Jquery Code:

$("select").each(function() {
  var sname = $(this).attr('name');
  var thissel = $(this);
  console.log();
  $(this).append('<input id="sel'+sname+'" type="hidden" name="' + sname + '" value="'+$(thissel).val()+'">');
  $(thissel).children("option").unwrap().each(function(i) {
    var btn = $('<div class="btn" name="' + sname + '">' + $(this).text() + '</div>');
    if (i==0) btn.addClass('on');
    $(this).replaceWith(btn);
  });
});

$(document).on('click', '.btn', function() {
  var name = $(this).attr("name");
  console.log($(this).html());
  $("#sel"+name).val($(this).html());
  var selector = '.btn[name="' + name + '"]'
  $(selector).removeClass('on');
  //$('.btn').removeClass('on');
  $(this).addClass('on');
});
neeh
  • 2,777
  • 3
  • 24
  • 32