Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Selectmenu #866

Closed
wants to merge 409 commits into from
This page is out of date. Refresh to see the latest.
1  Gruntfile.js
View
@@ -35,6 +35,7 @@ var
"progressbar",
"resizable",
"selectable",
+ "selectmenu",
"slider",
"spinner",
"tabs",
1  build/tasks/testswarm.js
View
@@ -25,6 +25,7 @@ var versions = {
"Progressbar": "progressbar/progressbar.html",
"Resizable": "resizable/resizable.html",
"Selectable": "selectable/selectable.html",
+ "Selectmenu": "selectmenu/selectmenu.html",
"Slider": "slider/slider.html",
"Sortable": "sortable/sortable.html",
"Spinner": "spinner/spinner.html",
1  demos/index.html
View
@@ -24,6 +24,7 @@
<li><a href="removeClass/">removeClass</a></li>
<li><a href="resizable/">resizable</a></li>
<li><a href="selectable/">selectable</a></li>
+ <li><a href="selectmenu/">selectmenu</a></li>
<li><a href="show/">show</a></li>
<li><a href="slider/">slider</a></li>
<li><a href="sortable/">sortable</a></li>
150 demos/selectmenu/custom_render.html
View
@@ -0,0 +1,150 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>jQuery UI Selectmenu - Default functionality</title>
+ <link rel="stylesheet" href="../../themes/base/jquery.ui.all.css">
+ <script src="../../jquery-1.9.1.js"></script>
+ <script src="../../ui/jquery.ui.core.js"></script>
+ <script src="../../ui/jquery.ui.widget.js"></script>
+ <script src="../../ui/jquery.ui.position.js"></script>
+ <script src="../../ui/jquery.ui.menu.js"></script>
+ <script src="../../ui/jquery.ui.selectmenu.js"></script>
+ <link rel="stylesheet" href="../demos.css">
+ <script>
+ $(function() {
+ $.widget( "custom.iconselectmenu", $.ui.selectmenu, {
+ _renderItem: function( ul, item ) {
+ var a, span,
+ li = $( "<li>" );
+
+ if ( item.disabled ) {
+ li.addClass( "ui-state-disabled" ).text( item.label );
+ } else {
+ a = $( "<a>", {
+ text: item.label,
+ href: "#"
+ }).appendTo( li );
+ span = $( "<span>", {
+ style: item.element.attr( "style" ),
+ "class": "ui-icon " + item.element.attr( "class" )
+ }).appendTo( a );
+ }
+
+ return li.appendTo( ul );
+ }
+ });
+
+ $( "#filesA" )
+ .iconselectmenu()
+ .iconselectmenu( "menuWidget" )
+ .addClass( "ui-menu-icons" );
+
+ $( "#filesB" )
+ .iconselectmenu()
+ .iconselectmenu( "menuWidget" )
+ .addClass( "ui-menu-icons customicons" );
+
+ $( "#people" )
+ .iconselectmenu()
+ .iconselectmenu( "menuWidget")
+ .addClass( "ui-menu-icons avatar" );
+ });
+ </script>
+ <style>
+ h2 {
+ margin: 30px 0 0 0
+ }
+ fieldset {
+ border: 0;
+ }
+ label {
+ display: block;
+ }
+ select {
+ width: 200px;
+ }
+
+ .ui-selectmenu-menu .ui-menu .ui-icon {
+ top: 0.4em;
+ }
+ .ui-selectmenu-menu .ui-menu .ui-menu-item a {
+ padding-left: 2em;
+ }
+
+ /* select with custom icons */
+ .ui-selectmenu-menu .ui-menu.customicons .ui-menu-item a {
+ padding: 0.5em 0 0.5em 3em;
+ }
+ .ui-selectmenu-menu .ui-menu.customicons .ui-menu-item a .ui-icon {
+ height: 24px;
+ width: 24px;
+ top: 0.2em;
+ }
+ .ui-icon.video {
+ background: url(images/24-video-square.png) 0 0 no-repeat;
+ }
+ .ui-icon.podcast {
+ background: url(images/24-podcast-square.png) 0 0 no-repeat;
+ }
+ .ui-icon.rss {
+ background: url(images/24-rss-square.png) 0 0 no-repeat;
+ }
+
+ /* select with CSS avatar icons */
+ option.avatar {
+ background-repeat: no-repeat !important;
+ padding-left: 20px;
+ }
+ .avatar .ui-icon {
+ background-position: left top;
+ }
+ </style>
+</head>
+<body>
+
+<div class="demo">
+
+<form action="#">
+
+ <h2>Selectmenu with framework icons</h2>
+ <fieldset>
+ <label for="filesA">Select a File:</label>
+ <select name="filesA" id="filesA">
+ <option value="jquery" class="ui-icon-script">jQuery.js</option>
+ <option value="jquerylogo" class="ui-icon-image">jQuery Logo</option>
+ <option value="jqueryui" class="ui-icon-script">ui.jQuery.js</option>
+ <option value="jqueryuilogo" selected="selected" class="ui-icon-image">jQuery UI Logo</option>
+ <option value="somefile">Some unknown file</option>
+ </select>
+ </fieldset>
+
+ <h2>Selectmenu with custom icon images</h2>
+ <fieldset>
+ <label for="filesB">Select a podcast:</label>
+ <select name="filesB" id="filesB">
+ <option value="mypodcast" class="podcast">John Resig Podcast</option>
+ <option value="myvideo" class="video">Scott Gonzales Video</option>
+ <option value="myrss" class="rss">jQuery RSS XML</option>
+ </select>
+ </fieldset>
+
+ <h2>Selectmenu with custom avatar 16x16 images as CSS background</h2>
+ <fieldset>
+ <label for="people">Select a Person:</label>
+ <select name="people" id="people">
+ <option value="1" class="avatar" style="background-image: url(http://www.gravatar.com/avatar/b3e04a46e85ad3e165d66f5d927eb609?d=monsterid&amp;r=g&amp;s=16);">John Resig</option>
+ <option value="2" class="avatar" style="background-image: url(http://www.gravatar.com/avatar/e42b1e5c7cfd2be0933e696e292a4d5f?d=monsterid&amp;r=g&amp;s=16);">Tauren Mills</option>
+ <option value="3" class="avatar" style="background-image: url(http://www.gravatar.com/avatar/bdeaec11dd663f26fa58ced0eb7facc8?d=monsterid&amp;r=g&amp;s=16);">Jane Doe</option>
+ </select>
+ </fieldset>
+
+</form>
+
+</div>
+
+<div class="demo-description">
+<p>The whole rendering process is extendable to make custom styling as easy as possible.</p>
+</div>
+</body>
+</html>
103 demos/selectmenu/default.html
View
@@ -0,0 +1,103 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>jQuery UI Selectmenu - Default functionality</title>
+ <link rel="stylesheet" href="../../themes/base/jquery.ui.all.css">
+ <script src="../../jquery-1.9.1.js"></script>
+ <script src="../../ui/jquery.ui.core.js"></script>
+ <script src="../../ui/jquery.ui.widget.js"></script>
+ <script src="../../ui/jquery.ui.position.js"></script>
+ <script src="../../ui/jquery.ui.menu.js"></script>
+ <script src="../../ui/jquery.ui.selectmenu.js"></script>
+ <link rel="stylesheet" href="../demos.css">
+ <script>
+ $(function() {
+ $( "#speed" ).selectmenu();
+
+ $( "#files" ).selectmenu();
+
+ $( "#number" )
+ .selectmenu()
+ .selectmenu( "menuWidget" )
+ .addClass( "overflow" );
+ });
+ </script>
+ <style>
+ fieldset {
+ border: 0;
+ }
+ label {
+ display: block;
+ margin: 30px 0 0 0;
+ }
+ select {
+ width: 200px;
+ }
+ .overflow {
+ height: 200px;
+ }
+ </style>
+</head>
+<body>
+
+<div class="demo">
+
+<form action="#">
+
+ <fieldset>
+ <label for="speed">Select a speed</label>
+ <select name="speed" id="speed">
+ <option value="Slower">Slower</option>
+ <option value="Slow">Slow</option>
+ <option value="Medium" selected="selected">Medium</option>
+ <option value="Fast">Fast</option>
+ <option value="Faster">Faster</option>
+ </select>
+
+ <label for="files">Select a file</label>
+ <select name="files" id="files">
+ <optgroup label="Scripts">
+ <option value="jquery">jQuery.js</option>
+ <option value="jqueryui">ui.jQuery.js</option>
+ </optgroup>
+ <optgroup label="Other files">
+ <option value="somefile">Some unknown file</option>
+ <option value="someotherfile">Some other file</option>
+ </optgroup>
+ </select>
+
+ <label for="number">Select a number</label>
+ <select name="number" id="number">
+ <option value="1">1</option>
+ <option value="2" selected="selected">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option value="11">11</option>
+ <option value="12">12</option>
+ <option value="13">13</option>
+ <option value="14">14</option>
+ <option value="15">15</option>
+ <option value="16">16</option>
+ <option value="17">17</option>
+ <option value="18">18</option>
+ <option value="19">19</option>
+ </select>
+ </fieldset>
+
+</form>
+
+</div>
+
+<div class="demo-description">
+<p>The Selectmenu widgets provides a styleable select element replacement. It will act as a proxy back to the original select element, controlling its state for form submission or serialization </p>
+<p>The datasource is a native select element. Supports optgroups.</p>
+</div>
+</body>
+</html>
BIN  demos/selectmenu/images/24-podcast-square.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  demos/selectmenu/images/24-rss-square.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  demos/selectmenu/images/24-video-square.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 demos/selectmenu/index.html
View
@@ -0,0 +1,15 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>jQuery UI Selectmenu Demos</title>
+</head>
+<body>
+
+<ul>
+ <li><a href="default.html">Default functionality</a></li>
+ <li><a href="custom_render.html">Custom item rendering functionality</a></li>
+</ul>
+
+</body>
+</html>
30 tests/unit/selectmenu/all.html
View
@@ -0,0 +1,30 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>jQuery UI Selectmenu Test Suite</title>
+
+ <script src="../../../jquery-1.9.1.js"></script>
+
+ <link rel="stylesheet" href="../../../external/qunit.css">
+ <link rel="stylesheet" href="../qunit-composite.css">
+ <script src="../../../external/qunit.js"></script>
+ <script src="../qunit-composite.js"></script>
+ <script src="../subsuite.js"></script>
+
+ <script>
+ testAllVersions( "selectmenu" );
+ </script>
+</head>
+<body>
+
+<h1 id="qunit-header">jQuery UI Selectmenu Test Suite</h1>
+<h2 id="qunit-banner"></h2>
+<div id="qunit-testrunner-toolbar"></div>
+<h2 id="qunit-userAgent"></h2>
+<ol id="qunit-tests"></ol>
+<div id="qunit-fixture">
+
+</div>
+</body>
+</html>
91 tests/unit/selectmenu/selectmenu.html
View
@@ -0,0 +1,91 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>jQuery UI Selectmenu Test Suite</title>
+
+ <script src="../../jquery.js"></script>
+ <link rel="stylesheet" href="../../../external/qunit.css">
+ <script src="../../../external/qunit.js"></script>
+ <script src="../../jquery.simulate.js"></script>
+ <script src="../testsuite.js"></script>
+ <script>
+ TestHelpers.loadResources({
+ css: [ "ui.core", "ui.menu" , "ui.selectmenu" ],
+ js: [
+ "ui/jquery.ui.core.js",
+ "ui/jquery.ui.widget.js",
+ "ui/jquery.ui.position.js",
+ "ui/jquery.ui.menu.js",
+ "ui/jquery.ui.selectmenu.js"
+ ]
+ });
+ </script>
+
+ <script src="selectmenu_common.js"></script>
+ <script src="selectmenu_core.js"></script>
+ <script src="selectmenu_events.js"></script>
+ <script src="selectmenu_methods.js"></script>
+ <script src="selectmenu_options.js"></script>
+
+ <script src="../swarminject.js"></script>
+</head>
+<body>
+
+<h1 id="qunit-header">jQuery UI Selectmenu Test Suite</h1>
+<h2 id="qunit-banner"></h2>
+<div id="qunit-testrunner-toolbar"></div>
+<h2 id="qunit-userAgent"></h2>
+<ol id="qunit-tests"></ol>
+<div id="qunit-fixture">
+ <div id="selectmenu-wrap1" class="selectmenu-wrap"></div>
+
+ <div id="selectmenu-wrap2" class="selectmenu-wrap">
+ <label for="speed">Select a speed:</label>
+ <select name="speed" id="speed">
+ <option value="Slower">Slower</option>
+ <option value="Slow">Slow</option>
+ <option value="Medium" selected="selected">Medium</option>
+ <option value="Fast">Fast</option>
+ <option value="Faster">Faster</option>
+ </select>
+ </div>
+
+ <label for="number">Select a number:</label>
+ <select name="number" id="number">
+ <option value="1">1</option>
+ <option value="2" selected="selected">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option value="11">11</option>
+ <option value="12">12</option>
+ <option value="13">13</option>
+ <option value="14">14</option>
+ <option value="15">15</option>
+ <option value="16">16</option>
+ <option value="17">17</option>
+ <option value="18">18</option>
+ <option value="19">19</option>
+ </select>
+
+ <label for="files">Select a file:</label>
+ <select name="files" id="files">
+ <optgroup label="Scripts">
+ <option value="jquery">jQuery.js</option>
+ <option value="jqueryui">ui.jQuery.js</option>
+ </optgroup>
+ <optgroup label="Other files">
+ <option value="somefile">Some unknown file</option>
+ <option value="someotherfile">Some other file</option>
+ </optgroup>
+ </select>
+
+</div>
+</body>
+</html>
22 tests/unit/selectmenu/selectmenu_common.js
View
@@ -0,0 +1,22 @@
+TestHelpers.commonWidgetTests( "selectmenu", {
+ defaults: {
+ appendTo: null,
+ disabled: false,
+ icons: {
+ button: "ui-icon-triangle-1-s"
+ },
+ position: {
+ my: "left top",
+ at: "left bottom",
+ collision: "none"
+ },
+
+ // callbacks
+ create: null,
+ change: null,
+ close: null,
+ focus: null,
+ open: null,
+ select: null
+ }
+});
188 tests/unit/selectmenu/selectmenu_core.js
View
@@ -0,0 +1,188 @@
+(function( $ ) {
+
+module( "selectmenu: core" );
+
+asyncTest( "accessibility", function() {
+ var links,
+ element = $( "#speed" ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" );
+
+ button.simulate( "focus" );
Scott González Owner

Whenever working with focus, the test must be async and use setTimeout( function() {} ) after a focus or blur occurs.

Felix Nagel Collaborator
fnagel added a note

I've changed this but its my first usage of asyncTest so please check if its implemented correctly.

Scott González Owner

Yup, it's correct :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ links = menu.find( "li.ui-menu-item a" );
+
+ expect( 12 + links.length * 2 );
+
+ setTimeout(function() {
+ equal( button.attr( "role" ), "combobox", "button link role" );
+ equal( button.attr( "aria-haspopup" ), "true", "button link aria-haspopup" );
+ equal( button.attr( "aria-expanded" ), "false", "button link aria-expanded" );
+ equal( button.attr( "aria-autocomplete" ), "list", "button link aria-autocomplete" );
+ equal( button.attr( "aria-owns" ), menu.attr("id"), "button link aria-owns" );
+ equal(
+ button.attr( "aria-labelledby" ),
+ links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
+ "button link aria-labelledby"
+ );
+ equal( button.attr( "tabindex" ), 0, "button link tabindex" );
+
+ equal( menu.attr( "role" ), "listbox", "menu role" );
+ equal( menu.attr( "aria-labelledby" ), button.attr( "id" ), "menu aria-labelledby" );
+ equal( menu.attr( "aria-hidden" ), "true", "menu aria-hidden" );
+ equal( menu.attr( "tabindex" ), 0, "menu tabindex" );
+ equal(
+ menu.attr( "aria-activedescendant" ),
+ links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
+ "menu aria-activedescendant"
+ );
+ $.each( links, function( index ){
+ equal( $( this ).attr( "role" ), "option", "menu link #" + index +" role" );
+ equal( $( this ).attr( "tabindex" ), -1, "menu link #" + index +" tabindex" );
+ });
+ start();
+ });
+});
+
+
+$.each([
+ {
+ type: "default",
+ selector: "#speed"
+ },
+ {
+ type: "optgroups",
+ selector: "#files"
+ }
+], function( i, settings ) {
+ asyncTest( "state synchronization - after keydown on button - " + settings.type, function () {
+ expect( 4 );
+
+ var links,
+ element = $( settings.selector ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" ),
+ selected = element.find( "option:selected" );
+
+ button.simulate( "focus" );
Scott González Owner

async focus

Felix Nagel Collaborator
fnagel added a note

see above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ setTimeout(function() {
+ links = menu.find("li.ui-menu-item a");
+
+ button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ equal(
+ menu.attr( "aria-activedescendant" ),
+ links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
+ "menu aria-activedescendant"
+ );
+ equal(
+ button.attr( "aria-activedescendant" ),
+ links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
+ "button aria-activedescendant"
+ );
+ equal(
+ element.find( "option:selected" ).val(),
+ selected.next( "option" ).val() ,
+ "original select state"
+ );
+ equal( button.text(), selected.next( "option" ).text(), "button text" );
+ start();
+ }, 1 );
+ });
+
+ asyncTest( "state synchronization - after click on item - " + settings.type, function () {
+ expect( 4 );
+
+ var links,
+ element = $( settings.selector ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" );
+
+ button.simulate( "focus" );
Scott González Owner

async focus

Felix Nagel Collaborator
fnagel added a note

see above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ setTimeout(function() {
+ links = menu.find("li.ui-menu-item a");
+
+ button.trigger( "click" );
+ menu.find( "a" ).last().simulate( "mouseover" ).trigger( "click" );
+ equal(
+ menu.attr( "aria-activedescendant" ),
+ links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
+ "menu aria-activedescendant"
+ );
+ equal(
+ button.attr( "aria-activedescendant" ),
+ links.eq( element[ 0 ].selectedIndex ).attr( "id" ),
+ "button aria-activedescendant"
+ );
+ equal(
+ element.find( "option:selected" ).val(),
+ element.find( "option" ).last().val(),
+ "original select state"
+ );
+ equal( button.text(), element.find( "option" ).last().text(), "button text" );
+ start();
+ }, 1 );
+ });
+
+ asyncTest( "state synchronization - after focus item and keydown on button - " + settings.type, function () {
+ expect( 4 );
+
+ var links,
+ element = $( settings.selector ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" ),
+ options = element.find( "option" );
+
+ // init menu
+ button.simulate( "focus" );
Scott González Owner

async focus

Felix Nagel Collaborator
fnagel added a note

see above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ setTimeout(function() {
+ links = menu.find( "li.ui-menu-item a" );
+ // open menu and click first item
+ button.trigger( "click" );
+ links.first().simulate( "mouseover" ).trigger( "click" );
+ // open menu again and hover item
+ button.trigger( "click" );
+ links.eq( 3 ).simulate( "mouseover" );
+ // close and use keyboard control on button
+ button.simulate( "keydown", { keyCode: $.ui.keyCode.ESCAPE } );
+ button.simulate( "focus" );
+ setTimeout(function() {
+ button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ equal( menu.attr( "aria-activedescendant" ), links.eq( 1 ).attr( "id" ), "menu aria-activedescendant" );
+ equal( button.attr( "aria-activedescendant" ), links.eq( 1 ).attr( "id" ), "button aria-activedescendant" );
+ equal( element.find( "option:selected" ).val(), options.eq( 1 ).val() , "original select state" );
+ equal( button.text(), options.eq( 1 ).text(), "button text" );
+ start();
+ }, 1 );
+ }, 1 );
+ });
+
+ asyncTest( "item looping - " + settings.type, function () {
+ expect( 2 );
+
+ var links,
+ element = $( settings.selector ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" );
+
+ // init menu
+ button.simulate( "focus" );
+
+ setTimeout(function() {
+ links = menu.find( "li.ui-menu-item a" );
+
+ button.trigger( "click" );
+ links.first().simulate( "mouseover" ).trigger( "click" );
+ button.simulate( "keydown", { keyCode: $.ui.keyCode.UP } );
+ equal( element[ 0 ].selectedIndex, 0, "No looping beyond first item" );
+
+ button.trigger( "click" );
+ links.last().simulate( "mouseover" ).trigger( "click" );
+ button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+ equal( element[ 0 ].selectedIndex + 1, links.length, "No looping behind last item" );
+ start();
+ }, 1 );
+ });
+});
+
+})( jQuery );
135 tests/unit/selectmenu/selectmenu_events.js
View
@@ -0,0 +1,135 @@
+(function ( $ ) {
+
+module( "selectmenu: events", {
+ setup: function () {
+ this.element = $( "#speed" );
+ }
+});
+
+asyncTest( "change", function () {
+ expect( 5 );
+
+ var optionIndex = 1,
+ button, menu, options;
+
+ this.element.selectmenu({
+ change: function ( event, ui ) {
+ ok( event, "change event fired on change" );
+ equal( event.type, "selectmenuchange", "event type set to selectmenuchange" );
+ equal( ui.item.index, optionIndex, "ui.item.index contains correct option index" );
+ equal( ui.item.element[ 0 ], options.eq( optionIndex )[ 0 ], "ui.item.element contains original option element" );
+ equal( ui.item.value, options.eq( optionIndex ).text(), "ui.item.value property updated correctly" );
+ }
+ });
+
+ button = this.element.selectmenu( "widget" );
+ menu = this.element.selectmenu( "menuWidget" ).parent();
+ options = this.element.find( "option" );
+
+ button.simulate( "focus" );
+
+ setTimeout(function() {
+ button.trigger( "click" );
+ menu.find( "a" ).eq( optionIndex ).simulate( "mouseover" ).trigger( "click" );
+ start();
+ }, 1 );
+});
+
+
+test( "close", function () {
+ expect( 4 );
+
+ this.element.selectmenu({
+ close: function ( event ) {
+ ok( event, "close event fired on close" );
+ equal( event.type, "selectmenuclose", "event type set to selectmenuclose" );
+ }
+ });
+
+ this.element.selectmenu( "open" ).selectmenu( "close" );
+
+ this.element.selectmenu( "open" );
+ $( "body" ).trigger( "click" );
+});
+
+
+asyncTest( "focus", function () {
+ expect( 12 );
+
+ var that = this,
+ optionIndex = this.element[ 0 ].selectedIndex + 1,
+ options = this.element.find( "option" ),
+ button, menu, links;
+
+ this.element.selectmenu({
+ focus: function ( event, ui ) {
+ ok( event, "focus event fired on element #" + optionIndex + " mouseover" );
+ equal( event.type, "selectmenufocus", "event type set to selectmenufocus" );
+ equal( ui.item.index, optionIndex, "ui.item.index contains correct option index" );
+ equal( ui.item.element[ 0 ], options.eq( optionIndex )[ 0 ], "ui.item.element contains original option element" );
+ }
+ });
+
+ button = this.element.selectmenu( "widget" );
+ menu = this.element.selectmenu( "menuWidget" );
+
+ button.simulate( "focus" );
+
+ setTimeout(function() {
+ button.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } );
+
+ button.trigger( "click" );
+ links = menu.find( "li.ui-menu-item a" );
+ optionIndex = 0;
+ links.eq( optionIndex ).simulate( "mouseover" );
+ optionIndex += 1;
+ links.eq( optionIndex ).simulate( "mouseover" );
+
+ // this tests for unwanted, additional focus event on close
+ that.element.selectmenu( "close" );
+ start();
+ }, 1 );
+});
+
+
+test( "open", function () {
+ expect( 2 );
+
+ this.element.selectmenu({
+ open: function ( event ) {
+ ok( event, "open event fired on open" );
+ equal( event.type, "selectmenuopen", "event type set to selectmenuopen" );
+ }
+ });
+
+ this.element.selectmenu( "open" );
+});
+
+
+asyncTest( "select", function () {
+ expect( 4 );
+
+ this.element.selectmenu({
+ select: function ( event, ui ) {
+ ok( event, "select event fired on item select" );
+ equal( event.type, "selectmenuselect", "event type set to selectmenuselect" );
+ equal( ui.item.index, optionIndex, "ui.item.index contains correct option index" );
+ equal( ui.item.element[ 0 ], options.eq( optionIndex )[ 0 ], "ui.item.element contains original option element" );
+ }
+ });
+
+ var button = this.element.selectmenu( "widget" ),
+ menu = this.element.selectmenu( "menuWidget" ).parent(),
+ options = this.element.find( "option" ),
+ optionIndex = 1;
+
+ button.simulate( "focus" );
+
+ setTimeout(function() {
+ button.trigger( "click" );
+ menu.find( "a" ).eq( optionIndex ).simulate( "mouseover" ).trigger( "click" );
+ start();
+ }, 1 );
+});
+
+})(jQuery);
165 tests/unit/selectmenu/selectmenu_methods.js
View
@@ -0,0 +1,165 @@
+(function( $ ) {
+
+module( "selectmenu: methods" );
+
+test( "destroy", function() {
+ expect( 1 );
+ domEqual( "#speed", function() {
+ $( "#speed" ).selectmenu().selectmenu( "destroy" );
+ });
+});
+
+
+test( "open / close", function() {
+ expect( 4 );
+
+ var element = $( "#speed" ).selectmenu(),
+ menu = element.selectmenu( "menuWidget" );
+
+ element.selectmenu( "open" );
+ ok( menu.is( ":visible" ), "open: menu visible" );
+ equal( menu.attr( "aria-hidden" ), "false", "open: menu aria-disabled" );
+
+ element.selectmenu( "close" );
+ ok( menu.is( ":hidden" ), "close: menu hidden" );
+ equal( menu.attr( "aria-hidden" ), "true", "close: menu aria-disabled" );
+});
+
+
+test( "enable / disable", function () {
+ expect(10);
+
+ var element = $( "#speed" ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" );
+
+ element.selectmenu( "disable" );
+ ok( element.selectmenu( "option", "disabled" ), "disable: widget option" );
+ equal( element.attr( "disabled" ), "disabled", "disable: native select disabled" );
+ equal( button.attr( "aria-disabled" ), "true", "disable: button wrapper ARIA" );
+ equal( button.attr( "tabindex" ), -1, "disable: button tabindex" );
+ equal( menu.attr( "aria-disabled" ), "true", "disable: menu wrapper ARIA" );
+
+ element.selectmenu( "enable" );
+ ok( !element.selectmenu( "option", "disabled" ), "enable: widget option" );
+ equal( element.attr( "disabled" ), undefined, "enable: native select disabled" );
+ equal( button.attr( "aria-disabled" ), "false", "enable: button wrapper ARIA" );
+ equal( button.attr( "tabindex" ), 0, "enable: button tabindex" );
+ equal( menu.attr( "aria-disabled" ), "false", "enable: menu wrapper ARIA" );
+});
+
+
+test( "refresh - structure", function () {
+ expect( 3 );
+
+ var element = $( "#speed" ).selectmenu(),
+ menu = element.selectmenu( "menuWidget" ).parent();
+
+ element.find( "option" ).eq( 2 ).remove();
+ element.find( "option" ).eq( 3 ).remove();
+ element.append( "<option value=\"added_option\">Added option</option>" );
+ element.find( "option" ).first()
+ .attr( "value", "changed_value" )
+ .text( "Changed value" );
+ element.selectmenu( "refresh" );
+
+ equal( element.find( "option" ).length, menu.find( "li" ).not( ".ui-selectmenu-optgroup" ).length, "menu item length" );
+ equal( element.find( "option" ).last().text(), menu.find( "li" ).not( ".ui-selectmenu-optgroup" ).last().text(), "added item" );
+ equal( element.find( "option" ).first().text(), menu.find( "li" ).not( ".ui-selectmenu-optgroup" ).first().text(), "changed item" );
+});
+
+asyncTest( "refresh - change selected option", function () {
+ expect( 3 );
+
+ var element = $( "#speed" ).selectmenu(),
+ button = element.selectmenu( "widget" );
+
+ equal( element.find( "option:selected" ).text(), button.text(), "button text after init" );
+
+ button.simulate( "focus" );
+
+ setTimeout(function() {
+ equal( element.find( "option:selected" ).text(), button.text(), "button text after focus" );
+
+ element[ 0 ].selectedIndex = 0;
+ element.selectmenu( "refresh" );
+
+ equal( element.find( "option:selected" ).text(), button.text(), "button text after changing selected option" );
+
+ start();
+ }, 1 );
+});
+
+
+test( "refresh - disabled select", function () {
+ expect( 4 );
+
+ var element = $( "#speed" ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" );
+
+ element.attr( "disabled", "disabled" );
+ element.selectmenu( "refresh" );
+
+ ok( element.selectmenu( "option", "disabled" ), "widget option" );
+ equal( button.attr( "aria-disabled" ), "true", "button wrapper ARIA" );
+ equal( button.attr( "tabindex" ), -1, "button tabindex" );
+ equal( menu.attr( "aria-disabled" ), "true", "menu wrapper ARIA" );
+});
+
+
+test( "refresh - disabled option", function () {
+ expect(1);
+
+ var disabledItem,
+ element = $( "#speed" ).selectmenu(),
+ menu = element.selectmenu( "menuWidget" ).parent();
+
+ element.attr( "disabled", "disabled" );
+ element.find( "option" ).eq( 2 ).attr( "disabled", "disabled" );
+ element.selectmenu( "refresh" );
+
+ disabledItem = menu.find( "li" ).not( ".ui-selectmenu-optgroup" ).eq(2);
+ ok( disabledItem.hasClass( "ui-state-disabled" ), "class" );
+});
+
+
+test( "refresh - disabled optgroup", function () {
+
+ var i, item,
+ element = $( "#files" ).selectmenu(),
+ menu = element.selectmenu( "menuWidget" ).parent(),
+ originalDisabledOptgroup = element.find( "optgroup" ).first(),
+ originalDisabledOptions = originalDisabledOptgroup.find( "option" );
+
+ expect( 2 + originalDisabledOptions.length );
+
+ originalDisabledOptgroup.attr( "disabled", "disabled" );
+ element.selectmenu( "refresh" );
+
+ item = menu.find( "li.ui-selectmenu-optgroup" ).first();
+ ok( item.hasClass( "ui-state-disabled" ), "class" );
+
+ equal( menu.find( "li" ).not( ".ui-selectmenu-optgroup" ).filter( ".ui-state-disabled" ).length, originalDisabledOptions.length, "disabled options" );
+ for ( i = 0; i < originalDisabledOptions.length; i++ ) {
+ item = item.next( "li" );
+ ok( item.hasClass( "ui-state-disabled" ), "item #" + i + ": class" );
+ }
+});
+
+test( "widget and menuWidget", function() {
+ expect( 4 );
+ var element = $( "#speed" ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" );
+
+ element.selectmenu( "refresh" );
+
+ equal( button.length, 1, "button: one element" );
+ ok( button.is( ".ui-selectmenu-button" ), "button: class" );
+
+ equal( menu.length, 1, "Menu Widget: one element" );
+ ok( menu.is( "ul.ui-menu" ), "Menu Widget: element and class" );
+});
+
+})( jQuery );
60 tests/unit/selectmenu/selectmenu_options.js
View
@@ -0,0 +1,60 @@
+(function ( $ ) {
+
+module( "selectmenu: options" );
+
+test( "appendTo another element", function () {
+ expect( 8 );
+
+ var detached = $( "<div>" ),
+ element = $( "#speed" ).selectmenu();
+ equal( element.selectmenu( "menuWidget" ).parent().parent()[ 0 ], document.body, "defaults to body" );
+ element.selectmenu( "destroy" );
+
+ element.selectmenu({
+ appendTo: ".selectmenu-wrap"
+ });
+ equal( element.selectmenu( "menuWidget" ).parent().parent()[ 0 ], $( "#selectmenu-wrap1" )[ 0 ], "first found element" );
+ equal( $( "#selectmenu-wrap2 .ui-selectmenu" ).length, 0, "only appends to one element" );
+ element.selectmenu( "destroy" );
+
+ $( "#selectmenu-wrap2" ).addClass( "ui-front" );
+ element.selectmenu();
+ equal( element.selectmenu( "menuWidget" ).parent().parent()[ 0 ], $( "#selectmenu-wrap2" )[ 0 ], "null, inside .ui-front" );
+ element.selectmenu( "destroy" );
+ $( "#selectmenu-wrap2" ).removeClass( "ui-front" );
+
+ element.selectmenu().selectmenu( "option", "appendTo", "#selectmenu-wrap1" );
+ equal( element.selectmenu( "menuWidget" ).parent().parent()[ 0 ], $( "#selectmenu-wrap1" )[ 0 ], "modified after init" );
+ element.selectmenu( "destroy" );
+
+ element.selectmenu({
+ appendTo: detached
+ });
+ equal( element.selectmenu( "menuWidget" ).parent().parent()[ 0 ], detached[ 0 ], "detached jQuery object" );
+ element.selectmenu( "destroy" );
+
+ element.selectmenu({
+ appendTo: detached[ 0 ]
+ });
+ equal( element.selectmenu( "menuWidget" ).parent().parent()[ 0 ], detached[ 0 ], "detached DOM element" );
+ element.selectmenu( "destroy" );
+
+ element.selectmenu().selectmenu( "option", "appendTo", detached );
+ equal( element.selectmenu( "menuWidget" ).parent().parent()[ 0 ], detached[ 0 ], "detached DOM element via option()" );
+ element.selectmenu( "destroy" );
+});
+
+
+test( "CSS styles", function () {
Scott González Owner

I don't think any other test suite does this. Considering the fact that corner classes are pretty ghetto to begin with, we probably don't want to start. The only exception would be if these classes are dynamic, such as RTL button sets.

Felix Nagel Collaborator
fnagel added a note

These classes change when the selectmenu is opened, so its a little dynamic.

Scott González Owner

Ok, they can stay then :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ expect( 2 );
+
+ var element = $( "#speed" ).selectmenu(),
+ button = element.selectmenu( "widget" ),
+ menu = element.selectmenu( "menuWidget" );
+
+ element.selectmenu( "open" );
+ ok( button.hasClass( "ui-corner-top" ) && !button.hasClass( "ui-corner-all" ) && button.find( "span.ui-icon" ).hasClass( "ui-icon-triangle-1-s" ), "button styles dropdown" );
+ ok( menu.hasClass( "ui-corner-bottom" ) && !menu.hasClass( "ui-corner-all" ), "menu styles dropdown" );
+});
+
+})( jQuery );
11 tests/visual/compound/dialog_widgets.html
View
@@ -22,8 +22,10 @@
<script src="../../../ui/jquery.ui.slider.js"></script>
<script src="../../../ui/jquery.ui.tabs.js"></script>
<script src="../../../ui/jquery.ui.tooltip.js"></script>
+ <script src="../../../ui/jquery.ui.selectmenu.js"></script>
<script>
$(function() {
+ $( "#dialog" ).dialog();
$( "[title]" ).tooltip();
$( "#accordion" ).accordion();
$( "#autocomplete" ).autocomplete({
@@ -45,7 +47,7 @@
}
});
$( "#tabs" ).tabs();
- $( "#dialog" ).dialog();
+ $( '#select' ).selectmenu();
$( "#dialog2" ).dialog({
autoOpen: false,
width: 100,
@@ -92,6 +94,13 @@
<div id="tabs-2">Phasellus mattis tincidunt nibh.</div>
<div id="tabs-3">Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.</div>
</div>
+ <select id="select">
+ <option>Slower</option>
+ <option>Slow</option>
+ <option>Medium</option>
+ <option>Fast</option>
+ <option>Faster</option>
+ </select>
</div>
<div id="dialog2">
Yay, another dialog.
53 tests/visual/compound/tabs_selectmenu.html
View
@@ -0,0 +1,53 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Compound Visual Test : Selectmenu in Tabs</title>
+ <link rel="stylesheet" href="../visual.css">
+ <link rel="stylesheet" href="../../../themes/base/jquery.ui.all.css">
+ <script src="../../../jquery-1.9.1.js"></script>
+ <script src="../../../ui/jquery.ui.core.js"></script>
+ <script src="../../../ui/jquery.ui.widget.js"></script>
+ <script src="../../../ui/jquery.ui.position.js"></script>
+ <script src="../../../ui/jquery.ui.menu.js"></script>
+ <script src="../../../ui/jquery.ui.selectmenu.js"></script>
+ <script src="../../../ui/jquery.ui.tabs.js"></script>
+ <script>
+ $(function() {
+ $( "#tabs" ).tabs();
+ $( "select" ).selectmenu();
+ });
+ </script>
+ <style>
+ select { width: 200px; }
+ </style>
+</head>
+<body>
+
+<div id="tabs">
+ <ul>
+ <li><a href="#tabs-1">First</a></li>
+ <li><a href="#tabs-2">Second</a></li>
+ </ul>
+ <div id="tabs-1">
+ <select>
+ <option>Slower</option>
+ <option>Slow</option>
+ <option>Medium</option>
+ <option>Fast</option>
+ <option>Faster</option>
+ </select>
+ </div>
+ <div id="tabs-2">
+ <select>
+ <option>Slower</option>
+ <option>Slow</option>
+ <option>Medium</option>
+ <option>Fast</option>
+ <option>Faster</option>
+ </select>
+ </div>
+</div>
+
+</body>
+</html>
248 tests/visual/selectmenu/selectmenu.html
View
@@ -0,0 +1,248 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Selectmenu Visual Test: Default</title>
+ <link rel="stylesheet" href="../../../themes/base/jquery.ui.all.css">
+ <script src="../../../jquery-1.9.1.js"></script>
+ <script src="../../../ui/jquery.ui.core.js"></script>
+ <script src="../../../ui/jquery.ui.widget.js"></script>
+ <script src="../../../ui/jquery.ui.position.js"></script>
+ <script src="../../../ui/jquery.ui.menu.js"></script>
+ <script src="../../../ui/jquery.ui.selectmenu.js"></script>
+ <script>
+ $(function() {
+ var log = $("#log"),
+ index = 0,
+ text;
+
+ function logger( event, ui ) {
+ text = "#" + index++ + " " + event.type.replace("selectmenu","");
+ if ( ui.item ) {
+ text += ": " + ui.item.index + " => " + ui.item.label;
+ }
+ $( "<p>" ).text( text ).prependTo( "#log" );
+ }
+
+ /* events */
+ var eventsSelectmenu = $('#control select').selectmenu({
+ open: logger,
+ close: logger,
+ focus : logger,
+ select: logger,
+ change: logger
+ });
+ eventsSelectmenu.show();
+
+ $("#destroy").click( function() {
+ eventsSelectmenu.selectmenu("destroy");
+ return false;
+ });
+
+ $("#refresh_add").click( function() {
+ eventsSelectmenu.append('<option value="fastsound">Speed of light</option>');
+ eventsSelectmenu.selectmenu("refresh");
+ return false;
+ });
+
+ $("#refresh_selected").click( function() {
+ eventsSelectmenu[0].selectedIndex = 0;
+ eventsSelectmenu.selectmenu("refresh");
+ return false;
+ });
+
+ $("#refresh").click( function() {
+ eventsSelectmenu.selectmenu("refresh");
+ return false;
+ });
+
+ $("#open").click( function() {
+ eventsSelectmenu.selectmenu("open");
+ return false;
+ });
+
+ $("#close").click( function() {
+ eventsSelectmenu.selectmenu("close");
+ return false;
+ });
+
+ /* disabled */
+ $('#disabled1, #disabled2, #disabled3').selectmenu();
+ var disabled4 = $('#disabled4').selectmenu();
+
+ $("#disable_select").on("click", function() {
+ if (disable_select) {
+ disable_select = false;
+ disabled4.selectmenu("disable");
+ } else {
+ disable_select = true;
+ disabled4.removeAttr("disabled");
+ }
+ disabled4.selectmenu("refresh");
+ return false;
+ });
+
+ $("#disable_option").on("click", function() {
+ if (disable_option) {
+ disable_option = false;
+ disabled4.find("option:eq(0)").attr("disabled", "disabled");
+ } else {
+ disable_option = true;
+ disabled4.find("option:eq(0)").removeAttr("disabled");
+ }
+ disabled4.selectmenu("refresh");
+ return false;
+ });
+
+ $("#disable_optgroup").on("click", function() {
+ if (disable_optgroup) {
+ disable_optgroup = false;
+ disabled4.find("optgroup:eq(0)").attr("disabled", "disabled");
+ } else {
+ disable_optgroup = true;
+ disabled4.find("optgroup:eq(0)").removeAttr("disabled");
+ }
+ disabled4.selectmenu("refresh");
+ return false;
+ });
+
+ /* empty */
+ $('.empty select').selectmenu();
+ });
+ </script>
+ <style>
+ body { font-size:62.5%; }
+ fieldset { border: 0; }
+ label { display: block; }
+ select { width: 200px; }
+
+ .ui-selectmenu-button { display: block; margin-bottom: 1em;}
+ </style>
+</head>
+<body>
+
+<div id="control">
+ <h2>Event logging tests</h2>
+ <form action="#">
+ <button id="open">Open</button>
+ <button id="close">Close</button>
+ <button id="refresh_add">Add item</button>
+ <button id="refresh_selected">Change to first item</button>
+ <button id="refresh">Refresh</button>
+ <button id="destroy">Destroy</button>
+ <fieldset>
+ <select>
+ <option value="Slower">Slower</option>
+ <option value="Slow">Slow</option>
+ <option value="Medium" selected="selected">Medium</option>
+ <option value="Fast">Fast</option>
+ <option value="Faster">Faster</option>
+ </select>
+ </fieldset>
+ </form>
+</div>
+
+<form action="#">
+ <h2>Disabled tests</h2>
+ <fieldset>
+ <label for="disabled1">Disabled select</label>
+ <select disabled="disabled" name="disabled1" id="disabled1">
+ <option value="Slower">Slower</option>
+ <option value="Slow">Slow</option>
+ <option value="Medium" selected="selected">Medium</option>
+ <option value="Fast">Fast</option>
+ <option value="Faster">Faster</option>
+ </select>
+
+ <label for="disabled2">Disabled options</label>
+ <select name="disabled2" id="disabled2">
+ <option value="1">1</option>
+ <option value="2" selected="selected">2</option>
+ <option value="3">3</option>
+ <option disabled="disabled" value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option disabled="disabled" value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option disabled="disabled" value="11">11</option>
+ <option value="12">12</option>
+ <option value="13">13</option>
+ <option disabled="disabled" value="14">14</option>
+ <option disabled="disabled" value="15">15</option>
+ <option value="16">16</option>
+ <option value="17">17</option>
+ <option value="18">18</option>
+ <option value="19">19</option>
+ </select>
+
+ <label for="disabled3">Disabled optgroup</label>
+ <select name="disabled3" id="disabled3">
+ <optgroup disabled="disabled" label="Scripts">
+ <option value="jquery">jQuery.js</option>
+ <option value="jqueryui">ui.jQuery.js</option>
+ </optgroup>
+ <optgroup label="Other files">
+ <option value="somefile">Some unknown file</option>
+ <option value="someotherfile">Some other file</option>
+ </optgroup>
+ </select>
+
+ <label for="disabled4">Disable specific element and refresh selectmenu on button click</label>
+ <select name="disabled4" id="disabled4">
+ <optgroup label="Scripts">
+ <option value="jquery">jQuery.js</option>
+ <option value="jqueryui">ui.jQuery.js</option>
+ </optgroup>
+ <optgroup label="Other files">
+ <option value="somefile">Some unknown file</option>
+ <option value="someotherfile">Some other file</option>
+ </optgroup>
+ </select>
+ <button id="disable_select">Toggle disable select</button>
+ <button id="disable_option">Toggle disable option</button>
+ <button id="disable_optgroup">Toggle disable optgroup</button>
+ </fieldset>
+
+ <h2>Empty tests</h2>
+ <fieldset class="empty">
+ <label for="empty1">Select with no option elements</label>
+ <select name="empty1" id="empty1"></select>
+
+ <label for="empty2">Select with one empty option element</label>
+ <select name="empty2" id="empty2">
+ <option value=""></option>
+ </select>
+
+ <label for="empty3">Select with some empty option elements</label>
+ <select name="empty3" id="empty3">
+ <option value="1">1</option>
+ <option value="2" selected="selected">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value=""></option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value=""></option>
+ <option value="9">9</option>
+ </select>
+
+ <label for="empty4">Select with empty optgroup</label>
+ <select id="empty4" name="empty4" class="empty4">
+ <optgroup label="Scripts"></optgroup>
+ <optgroup label="Other files">
+ <option value="somefile">Some unknown file</option>
+ <option value="someotherfile">Some other file</option>
+ </optgroup>
+ </select>
+ </fieldset>
+</form>
+
+<div style="position: absolute; top: 1em; right: 1em;">
+ Log:
+ <div id="log" style="height: 400px; width: 300px; overflow: auto; border: 1px solid #000;"></div>
+</div>
+
+</body>
+</html>
1  themes/base/jquery.ui.base.css
View
@@ -19,6 +19,7 @@
@import url("jquery.ui.progressbar.css");
@import url("jquery.ui.resizable.css");
@import url("jquery.ui.selectable.css");
+@import url("jquery.ui.selectmenu.css");
@import url("jquery.ui.slider.css");
@import url("jquery.ui.spinner.css");
@import url("jquery.ui.tabs.css");
58 themes/base/jquery.ui.selectmenu.css
View
@@ -0,0 +1,58 @@
+/*!
+ * jQuery UI Selectmenu @VERSION
+ * http://jqueryui.com
+ *
+ * Copyright 2013 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/selectmenu/#theming
+ */
+.ui-selectmenu-menu {
+ padding: 0;
+ margin: 0;
+ position: absolute;
+ top: 0;
Scott González Owner

left: 0 as well

Felix Nagel Collaborator
fnagel added a note

Done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ left: 0;
+ display: none;
+}
+.ui-selectmenu-menu .ui-menu {
+ overflow: auto;
+ /* Support: IE7 */
+ overflow-x: hidden;
+}
+.ui-selectmenu-menu .ui-menu-item a {
+ padding: 0.3em 1em;
+}
+.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
+ font-size: 1em;
+ font-weight: bold;
+ line-height: 1.5;
+ padding: 2px 0.4em;
+ margin: 0.5em 0 0 0;
+ height: auto;
+ border: 0;
+}
+.ui-selectmenu-open {
+ display: block;
+}
+.ui-selectmenu-button {
+ display: inline-block;
+ overflow: hidden;
+ position: relative;
+ text-decoration: none;
+ cursor: pointer;
+}
+.ui-selectmenu-button span.ui-icon {
+ right: 0.5em;
+ left: auto;
+ margin-top: -8px;
+ position: absolute;
+ top: 50%;
+}
+.ui-selectmenu-button span.ui-selectmenu-text {
+ text-align: left;
+ padding: 0.4em 2.1em 0.4em 1em;
Scott González Owner

Why are there so many fractional values? 0.3, 0.4, 0.5, 2.1

Felix Nagel Collaborator
fnagel added a note

We have similar top and button padding, some to the left and some more to the right to make sure text does not touch the arrow icon.

Jörn Zaefferer Owner

Alright, that's fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ display: block;
+ line-height: 1.4;
+}
Scott González Owner

Missing new line at end of file.

Felix Nagel Collaborator
fnagel added a note

Added.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
484 ui/jquery.ui.selectmenu.js
View
@@ -0,0 +1,484 @@
+/*!
+ * jQuery UI Selectmenu @VERSION
+ * http://jqueryui.com
+ *
+ * Copyright 2013 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/selectmenu
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ * jquery.ui.menu.js
+ */
+(function( $, undefined ) {
+
+$.widget( "ui.selectmenu", {
+ version: "@VERSION",
+ defaultElement: "<select>",
+ options: {
+ appendTo: null,
+ icons: {
+ button: "ui-icon-triangle-1-s"
+ },
+ position: {
+ my: "left top",
+ at: "left bottom",
+ collision: "none"
+ },
+
+ // callbacks
+ change: null,
+ close: null,
+ focus: null,
+ open: null,
+ select: null
+ },
+
+ _create: function() {
+ var selectmenuId = this.element.uniqueId().attr( "id" );
+ this.ids = {
+ element: selectmenuId,
+ button: selectmenuId + "-button",
+ menu: selectmenuId + "-menu"
+ };
+
+ this._drawButton();
+ this._drawMenu();
+
+ if ( this.options.disabled ) {
+ this.disable();
+ }
+ },
+
+ _drawButton: function() {
+ var tabindex = this.element.attr( "tabindex" );
+
+ // Fix existing label
+ this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
+ this._on( this.label, {
+ click: function( event ) {
+ this.button.focus();
+ event.preventDefault();
+ }
+ });
+
+ // Hide original select tag
+ this.element.hide();
+
+ // Create button
+ this.button = $( "<span>", {
+ "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
+ tabindex: tabindex || this.options.disabled ? -1 : 0,
+ id: this.ids.button,
+ width: this.element.outerWidth(),
+ role: "combobox",
+ "aria-expanded": "false",
+ "aria-autocomplete": "list",
+ "aria-owns": this.ids.menu,
+ "aria-haspopup": "true"
+ })
+ .insertAfter( this.element );
+
+ $( "<span>", {
+ "class": "ui-icon " + this.options.icons.button
+ }).prependTo( this.button );
+
+ this.buttonText = $( "<span>", {
+ "class": "ui-selectmenu-text"
+ })
+ .appendTo( this.button );
+ this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
+
+ this._on( this.button, this._buttonEvents );
+ this._hoverable( this.button );
+ this._focusable( this.button );
+ },
+
+ _drawMenu: function() {
+ var that = this;
+
+ // Create menu portion, append to body
+ this.menu = $( "<ul>", {
+ "aria-hidden": "true",
+ "aria-labelledby": this.ids.button,
+ id: this.ids.menu
+ });
+
+ // Wrap menu
+ this.menuWrap = $( "<div>", {
+ "class": "ui-selectmenu-menu",
+ outerWidth: this.button.outerWidth()
+ })
+ .append( this.menu )
+ .appendTo( this._appendTo() );
+
+ // Init menu widget
+ this.menuInstance = this.menu.menu({
+ select: function( event, ui ) {
+ var item = ui.item.data( "ui-selectmenu-item" );
+
+ that._select( item, event );
+
+ if ( that.isOpen ) {
+ event.preventDefault();
+ that.close( event );
+ }
+ },
+ focus: function( event, ui ) {
+ var item = ui.item.data( "ui-selectmenu-item" );
+
+ // prevent inital focus from firing and checks if its a newly focused item
+ if ( that.focusIndex != null && item.index !== that.focusIndex ) {
+ that._trigger( "focus", event, { item: item } );
+ if ( !that.isOpen ) {
+ that._select( item, event );
+ }
+ }
+ that.focusIndex = item.index;
+
+ that.button.attr( "aria-activedescendant", that.menuItems.eq( item.index ).attr( "id" ) );
+ },
+ role: "listbox"
+ })
+ .menu( "instance" );
+
+ // adjust menu styles to dropdown
+ this.menu.addClass( "ui-corner-bottom" ).removeClass( "ui-corner-all" );
+
+ // Make sure focus stays on selected item
+ this.menuInstance.delay = 999999999;
+ // Unbind uneeded Menu events
+ this.menuInstance._off( this.menu, "mouseleave" );
+ },
+
+ refresh: function() {
+ this.menu.empty();
+
+ var item,
+ options = this.element.find( "option" );
+
+ if ( !options.length ) {
+ return;
+ }
+
+ this._readOptions( options );
+ this._renderMenu( this.menu, this.items );
+
+ this.menu.menu( "refresh" );
+ this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" ).find( "a" );
+
+ item = this._getSelectedItem();
+
+ // Make sure menu is selected item aware
+ this.menu.menu( "focus", null, item );
+ this._setAria( item.data( "ui-selectmenu-item" ) );
+
+ // Set disabled state
+ this._setOption( "disabled", !!this.element.prop( "disabled" ) );
+ },
+
+ open: function( event ) {
+ if ( this.options.disabled ) {
+ return;
+ }
+ // Support: IE6-IE9 click doesn't trigger focus on the button
+ if ( !this.menuItems ) {
+ this.refresh();
+ }
+
+ this.isOpen = true;
+ this._toggleAttr();
+ this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
+
+ this._on( this.document, this._documentClick );
+
+ this._trigger( "open", event );
+ },
+
+ close: function( event ) {
+ if ( !this.isOpen ) {
+ return;
+ }
+
+ this.isOpen = false;
+ this._toggleAttr();
+
+ // Check if we have an item to select
+ if ( this.menuItems ) {
+ this.menuInstance.active = this._getSelectedItem();
+ }
+
+ this._off( this.document );
+
+ this._trigger( "close", event );
+ },
+
+ widget: function() {
+ return this.button;
+ },
+
+ menuWidget: function() {
+ return this.menu;
+ },
+
+ _renderMenu: function( ul, items ) {
+ var that = this,
+ currentOptgroup = "";
+
+ $.each( items, function( index, item ) {
+ if ( item.optgroup !== currentOptgroup ) {
+ $( "<li>", {
+ "class": "ui-selectmenu-optgroup" + ( item.element.parent( "optgroup" ).attr( "disabled" ) ? " ui-state-disabled" : "" ),
+ text: item.optgroup
+ }).appendTo( ul );
+ currentOptgroup = item.optgroup;
+ }
+ that._renderItemData( ul, item );
+ });
+ },
+
+ _renderItemData: function( ul, item ) {
+ return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
+ },
+
+ _renderItem: function( ul, item ) {
+ var li = $( "<li>" ),
+ a = $( "<a>", { href: "#" });
+
+ if ( item.disabled ) {
+ li.addClass( "ui-state-disabled" );
+ }
+ this._setText( a, item.label );
+
+ return li.append( a ).appendTo( ul );
+ },
+
+ _setText: function( element, value ) {
+ if ( value ) {
+ element.text( value );
+ } else {
+ element.html( "&#160;" );
+ }
+ },
+
+ _move: function( direction, event ) {
+ if ( direction === "first" || direction === "last" ) {
+ // Set focus manually for first or last item
+ this.menu.menu( "focus", event, this.menuItems[ direction ]() );
+ } else {
+ if ( direction === "previous" && this.menu.menu( "isFirstItem" ) || direction === "next" && this.menu.menu( "isLastItem" ) ) {
+ return;
+ }
+
+ // Move to and focus next or prev item
+ this.menu.menu( direction, event );
+ }
+ },
+
+ _getSelectedItem: function() {
+ return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
+ },
+
+ _toggle: function( event ) {
+ if ( this.isOpen ) {
+ this.close( event );
+ } else {
+ this.open( event );
+ }
+ },
+
+ _documentClick: {
+ click: function( event ) {
+ if ( this.isOpen && !$( event.target ).closest( "li.ui-state-disabled, li.ui-selectmenu-optgroup, #" + this.ids.button ).length ) {
+ this.close( event );
+ }
+ }
+ },
+
+ _buttonEvents: {
+ focus: function() {
+ // Init Menu on first focus
+ this.refresh();
+ // Reset focus class as its removed by ui.widget._setOption
+ this.button.addClass( "ui-state-focus" );
+ this._off( this.button, "focus" );
+ },
+ click: function( event ) {
+ this._toggle( event );
+ event.preventDefault();
+ },
+ keydown: function( event ) {
+ var prevDef = true;
Scott González Owner

Just do the call inline.

Felix Nagel Collaborator
fnagel added a note

This would need to add eight times event.preventDefault();

Scott González Owner

Just like the assignment was added eight times?

Felix Nagel Collaborator
fnagel added a note

Perhaps I did not understand you. I should remove the prefDef = false statements and use preventDefault instead in the needed cases, right?

Currently we use event.preventDefault(); in eight of ten cases.

Scott González Owner

Yes, every place that you have prevDef = false;, replace it with event.preventDefault(); and remove the variable.

Scott González Owner

Oh, nevermind. I see now that you're inverting it to avoid the duplication. Let's just leave it.

Felix Nagel Collaborator
fnagel added a note

;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.TAB:
+ case $.ui.keyCode.ESCAPE:
+ if ( this.isOpen ) {
+ this.close( event );
+ }
+ prevDef = false;
+ break;
+ case $.ui.keyCode.ENTER:
+ if ( this.isOpen ) {
+ this.menu.menu( "select", event );
+ }
+ break;
+ case $.ui.keyCode.UP:
+ if ( event.altKey ) {
+ this._toggle( event );
+ } else {
+ this._move( "previous", event );
+ }
+ break;
+ case $.ui.keyCode.DOWN:
+ if ( event.altKey ) {
+ this._toggle( event );
+ } else {
+ this._move( "next", event );
+ }
+ break;
+ case $.ui.keyCode.SPACE:
+ if ( this.isOpen ) {
+ this.menu.menu( "select", event );
+ } else {
+ this._toggle( event );
+ }
+ break;
+ case $.ui.keyCode.LEFT:
+ this._move( "previous", event );
+ break;
+ case $.ui.keyCode.RIGHT:
+ this._move( "next", event );
+ break;
+ case $.ui.keyCode.HOME:
+ case $.ui.keyCode.PAGE_UP:
+ this._move( "first", event );
+ break;
+ case $.ui.keyCode.END:
+ case $.ui.keyCode.PAGE_DOWN:
+ this._move( "last", event );
+ break;
+ default:
+ this.menu.trigger( event );
+ prevDef = false;
+ }
+ if ( prevDef ) {
+ event.preventDefault();
+ }
+ }
+ },
+
+ _select: function( item, event ) {
+ var oldIndex = this.element[ 0 ].selectedIndex;
+ // Change native select element
+ this.element[ 0 ].selectedIndex = item.index;
+ this._setText( this.buttonText, item.label );
+ this._setAria( item );
+ this._trigger( "select", event, { item: item } );
+
+ if ( item.index !== oldIndex ) {
+ this._trigger( "change", event, { item: item } );
+ }
+ },
+
+ _setAria: function( item ) {
+ var link = this.menuItems.eq( item.index ),
+ id = link.attr( "id" );
+
+ this.button.attr({
+ "aria-labelledby": id,
+ "aria-activedescendant": id
+ });
+ this.menu.attr( "aria-activedescendant", id );
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "icons" ) {
+ this.button.find( "span.ui-icon" )
+ .removeClass( this.options.icons.button )
+ .addClass( value.button );
+ }
+
+ this._super( key, value );
+
+ if ( key === "appendTo" ) {
+ this.menuWrap.appendTo( this._appendTo() );
+ }
+ if ( key === "disabled" ) {
+ this.menu.menu( "option", "disabled", value );
+ this.button
+ .toggleClass( "ui-state-disabled", !!value )
+ .attr( "aria-disabled", value );
+
+ if ( value ) {
+ this.element.attr( "disabled", "disabled" );
+ this.button.attr( "tabindex", -1 );
+ this.close();
+ } else {
+ this.element.removeAttr( "disabled" );
+ this.button.attr( "tabindex", 0 );
+ }
+ }
+ },
+
+ _appendTo: function() {
+ var element = this.options.appendTo;
+
+ if ( element ) {
+ element = element.jquery || element.nodeType ?
+ $( element ) :
+ this.document.find( element ).eq( 0 );
+ }
+
+ if ( !element ) {
+ element = this.element.closest( ".ui-front" );
+ }
+
+ if ( !element.length ) {
+ element = this.document[ 0 ].body;
+ }
+
+ return element;
+ },
+
+ _toggleAttr: function(){
+ this.button.toggleClass( "ui-corner-top", this.isOpen ).toggleClass( "ui-corner-all", !this.isOpen );
+ this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
+ this.menu.attr( "aria-hidden", !this.isOpen);
+ this.button.attr( "aria-expanded", this.isOpen);
+ },
+
+ _getCreateOptions: function() {
+ return { disabled: !!this.element.prop( "disabled" ) };
+ },
+
+ _readOptions: function( options ) {
+ var data = [];
+ options.each( function( index, item ) {
+ var option = $( item ),
+ optgroup = option.parent( "optgroup" );
+ data.push({
+ element: option,
+ index: index,
+ value: option.attr( "value" ),
+ label: option.text(),
+ optgroup: optgroup.attr( "label" ) || "",
+ disabled: optgroup.attr( "disabled" ) || option.attr( "disabled" )
+ });
+ });
+ this.items = data;
+ },
+
+ _destroy: function() {
+ this.menuWrap.remove();
+ this.button.remove();
+ this.element.show();
+ this.element.removeUniqueId();
+ this.label.attr( "for", this.ids.element );
+ }
+});
+
+}( jQuery ));
Something went wrong with that request. Please try again.