Selectmenu: improve positioning and keyboard control

This commit is contained in:
Felix Nagel 2011-09-26 01:18:19 +02:00
parent 55184e1e07
commit 3a8216fed8
3 changed files with 61 additions and 49 deletions

View File

@ -19,7 +19,7 @@
});
$('select#speedB').selectmenu({
dropdown: false,
wrapperElement: '<div class="overflow"/>',
wrapperElement: '<div class="overflow"/>'
});
$('select#filesC').selectmenu();
});
@ -38,7 +38,7 @@
<form action="#">
<fieldset>
<label for="speedA">Select a Speed:</label>
<select disabled="disabled" name="speedA" id="speedA">
<select name="speedA" id="speedA">
<option value="Slower">Slower</option>
<option value="Slow">Slow</option>
<option value="Medium" selected="selected">Medium</option>
@ -60,8 +60,8 @@
<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="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
@ -75,7 +75,7 @@
<br />
<label for="filesC">Select a file:</label>
<select name="filesC" id="filesC">
<optgroup disabled="disabled" label="scripts">
<optgroup label="scripts">
<option value="jquery">jQuery.js</option>
<option value="jqueryui">ui.jQuery.js</option>
</optgroup>

View File

@ -9,7 +9,7 @@
*/
.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 { width: auto; }
.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; }

View File

@ -35,8 +35,8 @@ $.widget( "ui.selectmenu", {
open: null,
focus: null,
select: null,
close: null,
// change: null,
close: null
// change: null
},
_create: function() {
@ -82,66 +82,68 @@ $.widget( "ui.selectmenu", {
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.newelement.bind({
'mousedown.selectmenu': function( event ) {
self._toggle( event );
return false;
})
.bind( 'click.selectmenu' , function() {
},
'click.selectmenu': function() {
return false;
})
.bind( 'keydown.selectmenu', function( event ) {
var ret = false;
},
'keydown.selectmenu': function( event ) {
var ret = true;
switch (event.keyCode) {
case $.ui.keyCode.TAB:
if ( self.opened ) self.close();
break;
case $.ui.keyCode.ENTER:
ret = true;
if ( self.opened ) self.list.menu( "select", self._getSelectedItem() );
ret = false;
break;
case $.ui.keyCode.SPACE:
self._toggle(event);
ret = false;
break;
case $.ui.keyCode.UP:
if ( event.altKey ) {
self._toggle( event );
} else {
self._previous();
self._move( "previous", event );
}
ret = false;
break;
case $.ui.keyCode.DOWN:
if ( event.altKey ) {
self._toggle( event );
} else {
self._next();
self._move( "next", event );
}
ret = false;
break;
case $.ui.keyCode.LEFT:
self._previous();
self._move( "previous", event );
ret = false;
break;
case $.ui.keyCode.RIGHT:
self._next();
self._move( "next", event );
ret = false;
break;
default:
self.list.trigger( event );
ret = false;
}
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) {
@ -149,8 +151,7 @@ $.widget( "ui.selectmenu", {
self.close( event );
}, 200 );
}
});
});
},
refresh: function() {
@ -163,7 +164,7 @@ $.widget( "ui.selectmenu", {
'aria-hidden': true,
'aria-labelledby': self.ids[0],
role: 'listbox',
id: self.ids[1],
id: self.ids[1]
});
self.listWrap = $( options.wrapperElement )
@ -179,7 +180,7 @@ $.widget( "ui.selectmenu", {
.data( 'element.selectelemenu', self.element )
.menu({
select: function( event, ui ) {
var item = ui.item.data( "item.selectmenu" );
var item = ui.item.data( "item.selectmenu" );
self._setSelected( event, item );
item.element = $ ( self.items[ item.index ] );
self._trigger( "select", event, { item: item } );
@ -191,18 +192,30 @@ $.widget( "ui.selectmenu", {
self._trigger( "focus", event, { item: item } );
}
})
.bind( 'mouseenter.selectelemenu', function() {
self.hover = true;
})
.bind( 'mouseleave .selectelemenu', function() {
self.hover = false;
.bind({
'mouseenter.selectelemenu': function() {
self.hover = true;
},
'mouseleave .selectelemenu': function() {
self.hover = false;
}
});
// adjust ARIA
self.list.find( "li" ).not( '.ui-selectmenu-optgroup' ).find( 'a' ).attr( 'role', 'option' );
if ( options.dropdown ) {
self.list
.addClass( 'ui-corner-bottom' )
.removeClass( 'ui-corner-all' );
}
// transfer disabled state
if ( self.element.attr( 'disabled' ) ) {
self.disable();
} else {
self.enable()
}
},
open: function( event ) {
@ -210,8 +223,7 @@ $.widget( "ui.selectmenu", {
options = this.options,
currentItem = self._getSelectedItem();
if ( !options.disabled ) {
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' );
@ -224,7 +236,7 @@ $.widget( "ui.selectmenu", {
}
self.listWrap.addClass( self.widgetBaseClass + '-open' );
self.list.focus().menu( "focus", null, currentItem );
self.list.menu( "focus", null, currentItem );
if ( !options.dropdown ) {
// center current item
@ -296,14 +308,14 @@ $.widget( "ui.selectmenu", {
).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");
_move: function( key, event ) {
if ( !this.opened ) {
this.list.menu( "focus", event, this._getSelectedItem() );
}
this.list.menu( key, event );
if ( !this.opened ) {
this.list.menu( "select", event );
}
},
_getSelectedItem: function() {