Monkeybrews
Monkeybrews

Reputation: 76

Add class to jQuery UI selectmenu <li> from original <option>

I'm looking to copy the custom classes added to the initial < option > over to the jQuery selectmenu UI generated list. I've tried using 'transferClasses: true' but that just transfers the main class across.

The select menu markup before jQuery UI is:

<select>
    <option>Option 1</option>
    <option>Option 2</option>
    <option class="child-option">Sub Option 1</option>
    <option class="child-option">Sub Option 2</option>
    <option>Option 3</option>
    ...
</select>

EDIT: What jQuery UI outputs at the moment:

<div class="ui-selectmenu-menu">
    <ul>
        <li class="ui-menu-item"><div>Option 1</div></li>
        <li class="ui-menu-item"><div>Option 2</div></li>
        <li class="ui-menu-item"><div>Sub Option 1</div></li>
        <li class="ui-menu-item"><div>Sub Option 2</div></li>
        <li class="ui-menu-item"><div>Option 3</div></li>
    </ul>
</div>

What I'd like jQuery UI to output:

<div class="ui-selectmenu-menu">
    <ul>
        <li class="ui-menu-item"><div>Option 1</div></li>
        <li class="ui-menu-item"><div>Option 2</div></li>
        <li class="ui-menu-item child-option"><div>Sub Option 1</div></li>
        <li class="ui-menu-item child-option"><div>Sub Option 2</div></li>
        <li class="ui-menu-item"><div>Option 3</div></li>
    </ul>
</div>

I've tried the solutions in similar request threads here and here but with no success.


EDIT 2:

The jQuery I'm using to generate the ul is:

$( "select" ).selectmenu({
    transferClasses: true,
});

Any help would be great!

Thanks

Upvotes: 1

Views: 5569

Answers (4)

Wouter Neuteboom
Wouter Neuteboom

Reputation: 846

If you have multiple selects:

$("select").each(function(index, select) {
    $(select).selectmenu({
        create: function( event, ui ) {
            $(select).next().addClass($(select).attr('class'));
        },
        open: function( event, ui ) {
            // Maybe remove classes or whatever
        }
    });
});

Upvotes: 0

Oleg Zhuravlev
Oleg Zhuravlev

Reputation: 11

There is a simple and direct way to add custom class to any jQuery UI widget - it's classes option.

Let's take a simple case with selectmenu jQuery widget.

HTML part is strict:

<select name="speed" id="speed" class="my-happy-decorated-class">
  <option>Slower</option>
  <option>Slow</option>
  <option selected="selected">Medium</option>
  <option>Fast</option>
  <option>Faster</option>
</select>

As usual, in order to decorate this ugly default stuff with cute jQuery UI just afterwards the document has been loaded we apply appropriate for the widget jQuery UI-function selectmenu():

<script>
  $(function() {
      $("#speed").selectmenu();
  } );
</script>

As a result we get something like this:

<select name="speed" id="speed" style="display: none;" class="my-happy-decorated-class">
            <option>Slower</option>
            <option>Slow</option>
            <option selected="selected">Medium</option>
            <option>Fast</option>
            <option>Faster</option>
        </select>
<span tabindex="0" id="speed-button" role="combobox" aria-expanded="false" aria-autocomplete="list" aria-owns="speed-menu" aria-haspopup="true" class="ui-selectmenu-button ui-button ui-widget ui-selectmenu-button-closed ui-corner-all" aria-activedescendant="ui-id-3" aria-labelledby="ui-id-3" aria-disabled="false"><span class="ui-selectmenu-icon ui-icon ui-icon-triangle-1-s"></span><span class="ui-selectmenu-text">Medium</span></span>
<span class="ui-selectmenu-icon ui-icon ui-icon-triangle-1-s"></span>
<span class="ui-selectmenu-text">Medium</span>
<span tabindex="0" id="speed-button" role="combobox" aria-expanded="false" aria-autocomplete="list" aria-owns="speed-menu" aria-haspopup="true" class="ui-selectmenu-button ui-button ui-widget ui-selectmenu-button-closed ui-corner-all" aria-activedescendant="ui-id-3" aria-labelledby="ui-id-3" aria-disabled="false"><span class="ui-selectmenu-icon ui-icon ui-icon-triangle-1-s"></span><span class="ui-selectmenu-text">Medium</span></span>

As you can see the initial tag <select ... class="my-happy-decorated-class"> got hidden and applying any style to class "my-happy-decorated-class" is useless.

This is the point where jQuery UI-option classes comes to help! Just apply the option to the widget by using the same selectmenu() command and you'll get the class in certain place in the result code:

<script>
  $(function() {
      $("#speed").selectmenu();
      $("#speed").selectmenu({
        classes: {
            "ui-selectmenu-button-closed": "my-happy-decorated-class"
        }
      });
  });
</script>

NOTE, that "ui-selectmenu-button-closed" is the default class, that jQuery UI sets to resulting HTML-tag used for displaying the widget! Names of default classes of different parts of any widget you can see with F12 in your browser.

Resulting HTML-code will be:

    <select name="speed" id="speed" style="display: none;" class="my-happy-decorated-class">
                <option>Slower</option>
                <option>Slow</option>
                <option selected="selected">Medium</option>
                <option>Fast</option>
                <option>Faster</option>
            </select>
    <span tabindex="0" id="speed-button" role="combobox" aria-expanded="false" aria-autocomplete="list" aria-owns="speed-menu" aria-haspopup="true" class="ui-selectmenu-button ui-button ui-widget
ui-selectmenu-button-closed my-happy-decorated-class
ui-corner-all" aria-activedescendant="ui-id-3" aria-labelledby="ui-id-3" aria-disabled="false"><span class="ui-selectmenu-icon ui-icon ui-icon-triangle-1-s"></span><span class="ui-selectmenu-text">Medium</span></span>
    <span class="ui-selectmenu-icon ui-icon ui-icon-triangle-1-s"></span>
    <span class="ui-selectmenu-text">Medium</span>
    <span tabindex="0" id="speed-button" role="combobox" aria-expanded="false" aria-autocomplete="list" aria-owns="speed-menu" aria-haspopup="true" class="ui-selectmenu-button ui-button ui-widget ui-selectmenu-button-closed ui-corner-all" aria-activedescendant="ui-id-3" aria-labelledby="ui-id-3" aria-disabled="false"><span class="ui-selectmenu-icon ui-icon ui-icon-triangle-1-s"></span><span class="ui-selectmenu-text">Medium</span></span>

As you can see your class my-happy-decorated-classwas added to the main visual resulting span of the widget and you are able to apply your styles to it.

Upvotes: 0

adosan
adosan

Reputation: 176

It seems there no way you can instruct selectmenu to preserve classes or other attributes.

But you can create your own selectmenu extension via widget factory.

//classyMenu widget extends/overrides selectmenu
$.widget("custom.classyMenu", $.ui.selectmenu, { 
  _renderItem: function(ul, item) {
    var li = $("<li>" ,{
      class: item.element.attr("class") //access the original item's class
    }),
    wrapper = $("<div>", {
      text: item.label
    });
    if ( item.disabled ) {
      li.addClass("ui-state-disabled");
    }
    return li.append( wrapper ).appendTo(ul);
  }
});


$("select").classyMenu(); //use classyMenu instad of selectmenu()

$("#open").click(function(){
  $("select").classyMenu("open");
});

$("#close").click(function(){
  $("select").classyMenu("close");
});
.bronze{color: #D1A684;}
.silver{color: silver;}
.gold{color: gold;}

ui-selectmenu-button{font-weight: bold}
<link href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>

<script
  src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
  integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
  crossorigin="anonymous"></script>

<button id="open">Open</button>
<button id="close">Close</button>

<br />

<select>
  <option value=""></option>
  <option value="1" class="bronze">1</option>
  <option value="2" class="silver">2</option>
  <option value="3" class="gold">3</option>
</select>

Upvotes: 2

j08691
j08691

Reputation: 207901

I was able to do it by looping over the newly created select menu using the open event. Apparently the actual items don't exist until the first time the open method is called.

$('select').selectmenu({
  open: function() {
      $('div.ui-selectmenu-menu li.ui-menu-item').each(function(idx){
      $(this).addClass( $('select option').eq(idx).attr('class') )
      })
  }
})
.child-option {
  background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<select>
  <option>Option 1</option>
  <option>Option 2</option>
  <option class="child-option">Sub Option 1</option>
  <option class="child-option">Sub Option 2</option>
  <option>Option 3</option>
</select>

Upvotes: 6

Related Questions