aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/selectmenu/default.html100
-rw-r--r--demos/selectmenu/index.html16
-rw-r--r--themes/base/jquery.ui.base.css1
-rw-r--r--themes/base/jquery.ui.selectmenu.css20
-rw-r--r--ui/jquery.ui.selectmenu.js368
5 files changed, 505 insertions, 0 deletions
diff --git a/demos/selectmenu/default.html b/demos/selectmenu/default.html
new file mode 100644
index 000000000..bd1ca7307
--- /dev/null
+++ b/demos/selectmenu/default.html
@@ -0,0 +1,100 @@
+<!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.6.2.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.button.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() {
+ $('select#speedA').selectmenu({
+ dropdown: false
+ });
+ $('select#speedB').selectmenu({
+ dropdown: false,
+ wrapperElement: '<div class="overflow"/>',
+ });
+ $('select#filesC').selectmenu();
+ });
+ </script>
+ <style>
+ form { margin: 200px 0 0 0; }
+ fieldset { border: 0; }
+ select { width: 200px; }
+ .overflow ul { height: 200px; overflow: auto; }
+ </style>
+</head>
+<body>
+
+<div class="demo">
+
+<form action="#">
+ <fieldset>
+ <label for="speedA">Select a Speed:</label>
+ <select disabled="disabled" name="speedA" id="speedA">
+ <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>
+ <br />
+ <br />
+ <br />
+ <label for="speedB">Select a Speed:</label>
+ <select name="speedB" id="speedB">
+ <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 disabled="disabled" value="11">11</option>
+ <option disabled="disabled" 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>
+ <br />
+ <br />
+ <br />
+ <label for="filesC">Select a file:</label>
+ <select name="filesC" id="filesC">
+ <optgroup disabled="disabled" label="scripts">
+ <option value="jquery">jQuery.js</option>
+ <option value="jqueryui">ui.jQuery.js</option>
+ </optgroup>
+ <optgroup label="Label with space">
+ <option disabled="disabled" value="somefile">Some unknown file</option>
+ <option value="someotherfile">Some other file</option>
+ </optgroup>
+ </select>
+ </fieldset>
+</form>
+
+</div><!-- End demo -->
+
+
+
+<div class="demo-description">
+<p>The Autocomplete widgets provides suggestions while you type into the field. Here the suggestions are tags for programming languages, give "ja" (for Java or JavaScript) a try.</p>
+<p>The datasource is a simple JavaScript array, provided to the widget using the source-option.</p>
+</div><!-- End demo-description -->
+
+</body>
+</html>
diff --git a/demos/selectmenu/index.html b/demos/selectmenu/index.html
new file mode 100644
index 000000000..909c3e262
--- /dev/null
+++ b/demos/selectmenu/index.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>jQuery UI Selectmenu Demos</title>
+ <link rel="stylesheet" href="../demos.css">
+</head>
+<body>
+ <div class="demos-nav">
+ <h4>Examples</h4>
+ <ul>
+ <li class="demo-config-on"><a href="default.html">Default functionality</a></li>
+ </ul>
+ </div>
+</body>
+</html>
diff --git a/themes/base/jquery.ui.base.css b/themes/base/jquery.ui.base.css
index a359c2ba4..6973ff0f0 100644
--- a/themes/base/jquery.ui.base.css
+++ b/themes/base/jquery.ui.base.css
@@ -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");
diff --git a/themes/base/jquery.ui.selectmenu.css b/themes/base/jquery.ui.selectmenu.css
new file mode 100644
index 000000000..d2353e882
--- /dev/null
+++ b/themes/base/jquery.ui.selectmenu.css
@@ -0,0 +1,20 @@
+/*
+ * jQuery UI Selectmenu @VERSION
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectmenu#theming
+ */
+
+.ui-selectmenu-menu { padding: 0; margin: 0; position:absolute; top: 0; display: none; }
+.ui-selectmenu-menu .ui-menu { padding: 0; }
+.ui-selectmenu-menu .ui-menu .ui-menu-item a { padding: 0.3em 1em 0.3em 1em; }
+.ui-selectmenu-menu .ui-menu .ui-menu-item a.ui-state-focus { margin: -1px 0 -1px -1px; }
+.ui-selectmenu-menu .ui-menu li.ui-state-disabled { margin: 0; padding: 0; }
+.ui-selectmenu-menu .ui-menu li.ui-selectmenu-optgroup { font-weight: bold; line-height: 1.5; padding: 2px 0.4em; margin: 0.5em 0 0 0; }
+.ui-selectmenu-open { display: block; }
+
+.ui-selectmenu-button span.ui-icon { right: 0.5em; left: auto; }
+.ui-selectmenu-button span.ui-button-text { text-align: left; padding: 0.4em 2.1em 0.4em 1em } \ No newline at end of file
diff --git a/ui/jquery.ui.selectmenu.js b/ui/jquery.ui.selectmenu.js
new file mode 100644
index 000000000..f2014d1f1
--- /dev/null
+++ b/ui/jquery.ui.selectmenu.js
@@ -0,0 +1,368 @@
+/*
+ * jQuery UI Selectmenu @VERSION
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectmenu
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ * jquery.ui.menu.js
+ * jquery.ui.button.js
+ */
+(function( $, undefined ) {
+
+$.widget( "ui.selectmenu", {
+ version: "@VERSION",
+ defaultElement: "<select>",
+ options: {
+ dropdown: true,
+ iconWidth: 26,
+ wrapperElement: "<div />",
+ appendTo: "body",
+ position: {
+ my: "left top",
+ at: "left bottom",
+ collision: "none"
+ },
+ source: null,
+ value: null,
+ // callbacks
+ open: null,
+ focus: null,
+ select: null,
+ close: null,
+ // change: null,
+ },
+
+ _create: function() {
+ var self = this,
+ options = this.options,
+ tabindex = this.element.attr( 'tabindex' )
+ // set a default id value, generate a new random one if not set by developer
+ selectmenuId = self.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 );
+
+ // quick array of button and menu id's
+ self.ids = [ selectmenuId + '-button', selectmenuId + '-menu' ];
+
+ // get options
+ self.items = self.element.find( 'option' );
+
+ // set options
+ options.value = self.element[0].value;
+ options.disabled = ( self.element.attr( 'disabled' ) ) ? true : false;
+
+ // catch click event of the label
+ self.element.bind( 'click.selectmenu', function() {
+ self.newelement.focus();
+ return false;
+ })
+ .hide();
+
+ // create button
+ self.newelement = $( '<a />', {
+ href: '#' + selectmenuId,
+ tabindex: ( tabindex ? tabindex : self.element.attr( 'disabled' ) ? 1 : 0 ),
+ id: self.ids[ 0 ],
+ css: {
+ width: self.element.width()
+ },
+ 'aria-disabled': options.disabled,
+ 'aria-owns': self.ids[ 1 ],
+ 'aria-haspopup': true
+ })
+ .addClass( self.widgetBaseClass + '-button' )
+ .button({
+ label: self.items.eq( this.element[0].selectedIndex ).text(),
+ icons: {
+ primary: ( options.dropdown ? 'ui-icon-triangle-1-s' : 'ui-icon-triangle-2-n-s' )
+ }
+ });
+
+
+ self.newelementWrap = $( options.wrapperElement )
+ .append( self.newelement )
+ .insertAfter( self.element );
+
+ self.newelement
+ .bind( 'mousedown.selectmenu' , function( event ) {
+ self._toggle( event );
+ return false;
+ })
+ .bind( 'click.selectmenu' , function() {
+ return false;
+ })
+ .bind( 'keydown.selectmenu', function( event ) {
+ var ret = false;
+ switch (event.keyCode) {
+ case $.ui.keyCode.TAB:
+ case $.ui.keyCode.ENTER:
+ ret = true;
+ break;
+ case $.ui.keyCode.SPACE:
+ self._toggle(event);
+ break;
+ case $.ui.keyCode.UP:
+ if ( event.altKey ) {
+ self._toggle( event );
+ } else {
+ self._previous();
+ }
+ break;
+ case $.ui.keyCode.DOWN:
+ if ( event.altKey ) {
+ self._toggle( event );
+ } else {
+ self._next();
+ }
+ break;
+ case $.ui.keyCode.LEFT:
+ self._previous();
+ break;
+ case $.ui.keyCode.RIGHT:
+ self._next();
+ break;
+ default:
+ self.list.trigger( event );
+ }
+ return ret;
+ });
+
+ // built menu
+ self.refresh();
+
+ // transfer disabled state
+ if ( self.element.attr( 'disabled' ) ) {
+ self.disable();
+ } else {
+ self.enable()
+ }
+
+ // document click closes menu
+ $( document ).bind( 'mousedown.selectmenu', function( event ) {
+ if ( self.opened && !self.hover) {
+ window.setTimeout( function() {
+ self.close( event );
+ }, 200 );
+ }
+ });
+
+ },
+
+ refresh: function() {
+ var self = this,
+ options = this.options;
+
+ // create menu portion, append to body
+ self.list = $( '<ul />', {
+ 'class': 'ui-widget ui-widget-content',
+ 'aria-hidden': true,
+ 'aria-labelledby': self.ids[0],
+ role: 'listbox',
+ id: self.ids[1],
+ });
+
+ self.listWrap = $( options.wrapperElement )
+ .addClass( self.widgetBaseClass + '-menu' )
+ .css( "width", ( options.dropdown ) ? self.element.width() : self.element.width() - options.iconWidth )
+ .append( self.list )
+ .appendTo( options.appendTo );
+
+ self._initSource();
+ self._renderMenu( self.list, options.source );
+
+ self.list
+ .data( 'element.selectelemenu', self.element )
+ .menu({
+ select: function( event, ui ) {
+ var item = ui.item.data( "item.selectmenu" );
+ self._setSelected( event, item );
+ item.element = $ ( self.items[ item.index ] );
+ self._trigger( "select", event, { item: item } );
+ self.close( event, true);
+ },
+ focus: function( event, ui ) {
+ var item = ui.item.data( "item.selectmenu" );
+ if ( !self.opened ) self._setSelected( event, item );
+ self._trigger( "focus", event, { item: item } );
+ }
+ })
+ .bind( 'mouseenter.selectelemenu', function() {
+ self.hover = true;
+ })
+ .bind( 'mouseleave .selectelemenu', function() {
+ self.hover = false;
+ });
+
+ if ( options.dropdown ) {
+ self.list
+ .addClass( 'ui-corner-bottom' )
+ .removeClass( 'ui-corner-all' );
+ }
+ },
+
+ open: function( event ) {
+ var self = this,
+ options = this.options,
+ currentItem = self._getSelectedItem();
+
+ if ( !options.disabled ) {
+
+ // close all other selectmenus
+ $( '.' + self.widgetBaseClass + '-open' ).not( self.newelement ).each( function() {
+ $( this ).children( 'ul.ui-menu' ).data( 'element.selectelemenu' ).selectmenu( 'close' );
+ });
+
+ if ( options.dropdown ) {
+ self.newelement
+ .addClass( 'ui-corner-top' )
+ .removeClass( 'ui-corner-all' );
+ }
+
+ self.listWrap.addClass( self.widgetBaseClass + '-open' );
+ self.list.focus().menu( "focus", null, currentItem );
+
+ if ( !options.dropdown ) {
+ // center current item
+ if ( self.list.css("overflow") == "auto" ) {
+ self.list.scrollTop( self.list.scrollTop() + currentItem.position().top - self.list.outerHeight()/2 + currentItem.outerHeight()/2 );
+ }
+ // calculate offset
+ var _offset = (self.list.offset().top - currentItem.offset().top + (self.newelement.outerHeight() - currentItem.outerHeight()) / 2);
+ $.extend( options.position, {
+ my: "left top",
+ at: "left top",
+ offset: "0 " + _offset
+ });
+ }
+
+ self.listWrap.position( $.extend({
+ of: this.newelementWrap
+ }, options.position ));
+
+ this.opened = true;
+ self._trigger( "open", event );
+ }
+ },
+
+ close: function( event, focus ) {
+ var self = this,
+ options = this.options;
+
+ if ( options.dropdown ) {
+ self.newelement
+ .addClass( 'ui-corner-all' )
+ .removeClass( 'ui-corner-top' );
+ }
+
+ self.listWrap.removeClass( self.widgetBaseClass + '-open' );
+ this.opened = false;
+
+ if (focus) self.newelement.focus();
+
+ self._trigger( "close", event );
+ },
+
+ _renderMenu: function( ul, items ) {
+ var self = this,
+ currentOptgroup = "";
+
+ $.each( items, function( index, item ) {
+ if ( item.optgroup != currentOptgroup ) {
+ var optgroup = $( '<li class="ui-selectmenu-optgroup">' + item.optgroup + '</li>' );
+ if ( $( self.items[ item.index ] ).parent( "optgroup" ).attr( "disabled" ) ) optgroup.addClass( 'ui-state-disabled' );
+ ul.append( optgroup );
+ currentOptgroup = item.optgroup;
+ }
+ self._renderItem( ul, item );
+ });
+ },
+
+ _renderItem: function( ul, item) {
+ return $( "<li />" )
+ .addClass( ( item.disabled ) ? 'ui-state-disabled' : '' )
+ .data( "item.selectmenu", item )
+ .append( $( "<a />", {
+ text: item.label,
+ href: '#',
+ click: function( event ) {
+ event.preventDefault();
+ }
+ })
+ ).appendTo( ul );
+ },
+
+ _previous: function() {
+ this.list.menu( "focus", null, this._getSelectedItem() );
+ this.list.menu("previous");
+ },
+
+ _next: function() {
+ this.list.menu( "focus", null, this._getSelectedItem() );
+ this.list.menu("next");
+ },
+
+ _getSelectedItem: function() {
+ return this.list.find( "li" ).not( '.ui-selectmenu-optgroup' ).eq( this.element[0].selectedIndex );
+ },
+
+ _setSelected: function( event, item ) {
+ this.newelement.children( '.ui-button-text' ).text( item.label );
+ this.element[0].selectedIndex = item.index;
+ this.options.value = item.value;
+ },
+
+ _toggle: function( event ) {
+ if ( this.opened ) {
+ this.close( event );
+ } else {
+ this.open( event );
+ }
+ },
+
+ _setOption: function( key, value ) {
+ this._super( "_setOption", key, value );
+ if ( key === "appendTo" ) {
+ this.listWrap.appendTo( $( value || "body", this.element[0].ownerDocument )[0] );
+ }
+ if ( key === "value" && value) {
+ this.element[0].value = value;
+ }
+ if ( key === "disabled" ) {
+ this.newelement.button( "option", "disabled", value );
+ this.list.attr( "aria-disabled", value );
+ this.close();
+ }
+ },
+
+ _initSource: function() {
+ if ( !$.isArray( this.options.source ) ) {
+ var data = [];
+ $.each( this.items, function( index, item ) {
+ var option = $( item ),
+ optgroup = option.parent( "optgroup" );
+ data.push({
+ index: index,
+ value: option.attr( 'value' ),
+ label: option.text(),
+ optgroup: optgroup.attr("label") || false,
+ disabled: optgroup.attr( "disabled" ) || option.attr( "disabled" )
+ });
+ });
+ this.options.source = data;
+ }
+ },
+
+ _destroy: function() {
+ this.listWrap.remove();
+ this.newelementWrap.remove();
+ this.element.show().unbind( '.selectmenu' );
+ $( document ).unbind( '.selectmenu' );
+ }
+});
+
+}( jQuery ));