aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Nagel <info@felixnagel.com>2011-09-02 00:21:09 +0200
committerFelix Nagel <info@felixnagel.com>2011-09-22 01:34:49 +0200
commitecd8ea4a1c40b6056381e920dd03add3db52d4dd (patch)
tree314ff4122a1bc4f39c47c500801454cb51604c50
parent25f2113cc11b732224f98a9755a48d27177ed7c1 (diff)
downloadjquery-ui-ecd8ea4a1c40b6056381e920dd03add3db52d4dd.tar.gz
jquery-ui-ecd8ea4a1c40b6056381e920dd03add3db52d4dd.zip
Selectmenu: basic implementation
-rw-r--r--demos/selectmenu/default.html67
-rw-r--r--demos/selectmenu/index.html16
-rw-r--r--themes/base/jquery.ui.base.css1
-rw-r--r--themes/base/jquery.ui.selectmenu.css16
-rw-r--r--ui/jquery.ui.selectmenu.js300
5 files changed, 400 insertions, 0 deletions
diff --git a/demos/selectmenu/default.html b/demos/selectmenu/default.html
new file mode 100644
index 000000000..e1b4517c3
--- /dev/null
+++ b/demos/selectmenu/default.html
@@ -0,0 +1,67 @@
+<!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').selectmenu();
+ });
+ </script>
+ <style>
+ form { margin: 200px 0 0 0; }
+ fieldset { border: 0; }
+ select { width: 200px; }
+ </style>
+</head>
+<body>
+
+<div class="demo">
+
+<form action="#">
+ <fieldset>
+ <label for="speedA">Select a Speed:</label>
+ <select name="speedA" id="speedA">
+ <option value="Slower">Slower</option>
+ <option value="Slow" selected="selected">Slow</option>
+ <option value="Medium">Medium</option>
+ <option value="Fast">Fast</option>
+ <option value="Faster">Faster</option>
+ </select>
+ <br />
+ <br />
+ <br />
+ <label for="filesC">Select a file:</label>
+ <select name="filesC" id="filesC">
+ <optgroup label="scripts">
+ <option value="jquery">jQuery.js</option>
+ <option value="jqueryui">ui.jQuery.js</option>
+ </optgroup>
+ <optgroup label="Label with space">
+ <option 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..d64084d60
--- /dev/null
+++ b/themes/base/jquery.ui.selectmenu.css
@@ -0,0 +1,16 @@
+/*
+ * 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-open { display: block; }
+
+.ui-button span.ui-icon { right: 0.5em; left: auto; }
+.ui-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..c8ee50a75
--- /dev/null
+++ b/ui/jquery.ui.selectmenu.js
@@ -0,0 +1,300 @@
+/*
+ * 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
+ */
+(function( $, undefined ) {
+
+// used to prevent race conditions with remote data sources
+var requestIndex = 0;
+
+$.widget( "ui.selectmenu", {
+ version: "@VERSION",
+ defaultElement: "<select>",
+ options: {
+ wrapperElement: "<div />",
+ appendTo: "body",
+ position: {
+ my: "left top",
+ at: "left bottom",
+ collision: "none"
+ },
+ source: null,
+
+ iconWidth: 26,
+
+ // 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
+ var 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' );
+
+ // catch click event of the label
+ self.element.bind( 'click.selectmenu', function() {
+ self.newelement.focus();
+ return false;
+ });
+
+ // create button
+ self.newelement = $( '<a />', {
+ href: '#' + selectmenuId,
+ tabindex: (tabindex ? tabindex : self.element.attr( 'disabled' ) ? 1 : 0),
+ 'aria-haspopup': true,
+ 'aria-owns': self.ids[ 1 ],
+ css: {
+ width: self.element.width()
+ }
+ }).button({
+ label: self.items.eq( self.element[0].selectedIndex ).text(),
+ icons: {
+ primary: "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.list.trigger( event );
+ if ( options.open ) self.list.focus();
+ }
+ break;
+ case $.ui.keyCode.DOWN:
+ if (event.altKey) {
+ self._toggle( event );
+ } else {
+ self.list.trigger( event );
+ if ( options.open ) self.list.focus();
+ }
+ break;
+ case $.ui.keyCode.LEFT:
+ // event.which = 40;
+ event.keyCode = 40;
+ self.list.trigger( event );
+ break;
+ case $.ui.keyCode.RIGHT:
+ // event.which = 38;
+ event.keyCode = 38;
+ self.list.trigger( event );
+ break;
+ default:
+ self.list.trigger( event );
+ }
+ return ret;
+ });
+
+
+ // 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],
+ css: {
+ // width: self.element.width() - options.iconWidth
+ width: self.element.width()
+ }
+ });
+
+ self.listWrap = $( options.wrapperElement )
+ .addClass( self.widgetBaseClass + '-menu' )
+ .append( self.list )
+ .appendTo( options.appendTo );
+
+ self._renderMenu( self.list, self._initSource() );
+
+ self.list.menu({
+ select: function( event, ui ) {
+ var item = ui.item.data( "item.selectmenu" );
+ console.log(item);
+
+ self.newelement.children( 'span.ui-button-text' ).text( item.label );
+ self.value( item.value );
+ self.close( event, true);
+ },
+ focus: function( event, ui ) {
+ var item = ui.item.data( "item.selectmenu" );
+ if ( !options.open ) self.newelement.children( 'span.ui-button-text' ).text( item.label );
+ }
+ });
+
+ // document click closes menu
+ $( document ).bind( 'mousedown.selectmenu', function( event ) {
+ if ( self.options.open ) {
+ window.setTimeout( function() {
+ self.close( event );
+ }, 200 );
+ }
+ });
+
+ },
+
+ _toggle: function( event ) {
+ if ( this.options.open ) {
+ this.close( event );
+ } else {
+ this.open( event );
+ }
+ },
+
+ open: function( event ) {
+ var self = this,
+ options = this.options;
+
+ self.listWrap.addClass( self.widgetBaseClass + '-open' );
+ this.options.open = true;
+
+ self.listWrap.position( $.extend({
+ of: this.newelementWrap
+ }, options.position ));
+ },
+
+
+ close: function( event, focus ) {
+ var self = this,
+ options = this.options;
+
+ self.listWrap.removeClass( self.widgetBaseClass + '-open' );
+ this.options.open = false;
+
+ if (focus) self.newelement.focus();
+ },
+
+ _renderMenu: function( ul, items ) {
+ var self = this,
+ currentOptgroup = "";
+ $.each( items, function( index, item ) {
+ if ( item.optgroup != currentOptgroup ) {
+ ul.append( "<li class='ui-selectmenu-optgroup'>" + item.optgroup + "</li>" );
+ currentOptgroup = item.optgroup;
+ }
+ self._renderItem( ul, item );
+ });
+ },
+
+ _renderItem: function( ul, item) {
+ return $( "<li />" )
+ .data( "item.selectmenu", item )
+ .append( $( "<a />", {
+ text: item.label,
+ href: '#nogo'
+ })
+ ).appendTo( ul );
+ },
+
+ _destroy: function() {
+ clearTimeout( this.searching );
+ this.element
+ .removeClass( "ui-autocomplete-input" )
+ .removeAttr( "autocomplete" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-autocomplete" )
+ .removeAttr( "aria-haspopup" );
+ this.menu.element.remove();
+ },
+
+ _setOption: function( key, value ) {
+ this._super( "_setOption", key, value );
+ if ( key === "source" ) {
+ this._initSource();
+ }
+ if ( key === "appendTo" ) {
+ this.listWrap.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
+ }
+ // if ( key === "disabled" && value && this.xhr ) {
+ // this.xhr.abort();
+ // }
+ },
+
+ _initSource: function() {
+ var data = [];
+ // data = [
+ // { label: "anders", optgroup: "" },
+ // { label: "andreas", optgroup: "" },
+ // { label: "antal", optgroup: "" },
+ // { label: "annhhx10", optgroup: "Products" },
+ // { label: "annk K12", optgroup: "Products" },
+ // { label: "annttop C13", optgroup: "Products" },
+ // { label: "anders andersson", optgroup: "People" },
+ // { label: "andreas andersson", optgroup: "People" },
+ // { label: "andreas johnson", optgroup: "People" }
+ // ];
+
+ $.each( this.items, function( index, item ) {
+ var option = $( item );
+ data.push({
+ value: option.attr( 'value' ),
+ label: option.text(),
+ optgroup: option.parent("optgroup").attr("label") || false
+ });
+ });
+ // console.log(data);
+ return data;
+ },
+
+ value: function( newValue ) {
+ if (arguments.length) {
+ this.element[0].value = newValue;
+ } else {
+ return this.element[0].value;
+ }
+ }
+
+ // index: function( newValue ) {
+ // if ( arguments.length ) {
+ // this.element[0].selectedIndex = newValue;
+ // } else {
+ // return this.element[0].selectedIndex;
+ // }
+ // }
+});
+
+}( jQuery ));