r2780 - updated and abstracted out focus and selection methods, which also fixes keyboard events ...
Author: scottjehl
Date: Tue Jun 16 10:20:41 2009
New Revision: 2780
Modified:
branches/labs/selectmenu/ui.selectmenu.js
Log:
updated and abstracted out focus and selection methods, which also fixes
keyboard events within optgroups
Modified: branches/labs/selectmenu/ui.selectmenu.js
==============================================================================
--- branches/labs/selectmenu/ui.selectmenu.js (original)
+++ branches/labs/selectmenu/ui.selectmenu.js Tue Jun 16 10:20:41 2009
@@ -44,60 +44,61 @@
//click toggle for menu visibility
this.newelement
- .bind('mousedown', function(){
- self._toggle();
- //make sure a click won't open/close instantly
- if(o.style == "popup"){
- self._safemouseup = false;
- setTimeout(function(){self._safemouseup = true;}, 500);
- }
- return false;
- })
- .bind('click',function(){
- return false;
- })
- .keydown(function(event){
- var ret = true;
- switch (event.keyCode) {
- case $.ui.keyCode.ENTER:
- case $.ui.keyCode.SPACE:
- ret = false;
- self._toggle();
- break;
- case $.ui.keyCode.UP:
- case $.ui.keyCode.LEFT:
- ret = false;
-
self.list.find('li.ui-selectmenu-item-selected').prev().trigger('mouseup');
- break;
- case $.ui.keyCode.DOWN:
- case $.ui.keyCode.RIGHT:
- ret = false;
-
self.list.find('li.ui-selectmenu-item-selected').next().trigger('mouseup');
- break;
- case $.ui.keyCode.TAB:
- ret = true;
- break;
- default:
- ret = false;
- self._typeAhead(event.keyCode, 'mouseup');
- break;
- }
- return ret;
- })
- .bind('mouseover focus', function(){
$(this).addClass('ui-selectmenu-focus ui-state-hover'); })
- .bind('mouseout blur', function(){
- $(this).removeClass('ui-selectmenu-focus ui-state-hover');
- });
+ .bind('mousedown', function(){
+ self._toggle();
+ //make sure a click won't open/close instantly
+ if(o.style == "popup"){
+ self._safemouseup = false;
+ setTimeout(function(){self._safemouseup = true;}, 500);
+ }
+ return false;
+ })
+ .bind('click',function(){
+ return false;
+ })
+ .keydown(function(event){
+ var ret = true;
+ switch (event.keyCode) {
+ case $.ui.keyCode.ENTER:
+ case $.ui.keyCode.SPACE:
+ ret = false;
+ self._toggle();
+ break;
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.LEFT:
+ ret = false;
+ self._moveSelection(-1);
+ break;
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.RIGHT:
+ ret = false;
+ self._moveSelection(1);
+ break;
+ case $.ui.keyCode.TAB:
+ ret = true;
+ break;
+ default:
+ ret = false;
+ self._typeAhead(event.keyCode, 'mouseup');
+ break;
+ }
+ return ret;
+ })
+ .bind('mouseover focus', function(){
$(this).addClass('ui-selectmenu-focus ui-state-hover'); })
+ .bind('mouseout blur', function(){
+ $(this).removeClass('ui-selectmenu-focus ui-state-hover');
+ });
//document click closes menu
- $(document).mousedown(function(){
- self.close();
- });
+ $(document)
+ .mousedown(function(){
+ self.close();
+ });
//change event on original selectmenu
- this.element
- .click(function(){ this._refreshValue(); })
- .focus(function(){ this.newelement.focus(); });
+ this.element
+ .click(function(){ this._refreshValue(); })
+ .focus(function(){ this.newelement.focus(); });
//create menu portion, append to body
@@ -202,6 +203,9 @@
if(o.maxHeight && o.maxHeight < this.list.height()){
this.list.height(o.maxHeight);
}
+
+ //save reference to actionable li's (not group label li's)
+ this._optionLis = this.list.find('li:not(.ui-selectmenu-group)');
//transfer menu click to menu button
this.list
@@ -212,33 +216,28 @@
case $.ui.keyCode.UP:
case $.ui.keyCode.LEFT:
ret = false;
- if($(event.target).parents('li:eq(0)').prev().size()>0){
-
$(event.target).blur().parents('li:eq(0)').prev().find('a:eq(0)').focus();
- }
+ self._moveFocus(-1);
break;
case $.ui.keyCode.DOWN:
case $.ui.keyCode.RIGHT:
ret = false;
- if($(event.target).parents('li:eq(0)').next().size()>0){
-
$(event.target).blur().parents('li:eq(0)').next().find('a:eq(0)').focus();
- }
+ self._moveFocus(1);
break;
case $.ui.keyCode.HOME:
- $(event.target).blur();
- self.list.find('a:first').focus();
+ ret = false;
+ self._moveFocus(':first');
break;
case $.ui.keyCode.PAGE_UP:
ret = false;
- self._scrollPage(event.target, 'up');
+ self._scrollPage('up');
break;
case $.ui.keyCode.PAGE_DOWN:
ret = false;
- self._scrollPage(event.target, 'down');
+ self._scrollPage('down');
break;
case $.ui.keyCode.END:
ret = false;
- $(event.target).blur();
- self.list.find('a:last').focus();
+ self._moveFocus(':last');
break;
case $.ui.keyCode.ENTER:
case $.ui.keyCode.SPACE:
@@ -379,24 +378,10 @@
return newText;
},
- _scrollPage: function(curTarget,direction){
- var numPerPage = Math.floor(this.list.outerHeight() /
this.list.find('li:first').outerHeight());
- var currentIndex = parseInt(
$(curTarget).parents('li:eq(0)').data('index') );
- var nextIndex = (direction == 'up') ? currentIndex - numPerPage :
currentIndex + numPerPage;
- nextIndex = ':eq('+nextIndex+')';
- if(this.list.find('li' + nextIndex).size() < 1){
- nextIndex = (direction == 'up') ? ':first' : ':last';
- }
- this.list.find('li' + nextIndex + ' a').focus();
- },
-
- _selectedIndex: function(){
- return this.element[0].selectedIndex;
- },
-
_selectOptions: function(){
var opts = [];
var self = this;
+ //this should use map
this.element.find('option').each(function(i){
opts.push({
value: jQuery(this).attr('value'),
@@ -407,6 +392,45 @@
});
});
return opts;
+ },
+
+ _selectedIndex: function(){
+ return this.element[0].selectedIndex;
+ },
+
+ _selectedOptionLi: function(){
+ return this._optionLis.eq(this._selectedIndex());
+ },
+
+ _focusedOptionLi: function(){
+ return this.list.find('.ui-selectmenu-item-focus');
+ },
+
+ _moveSelection: function(amt){
+ var currIndex = parseInt(this._selectedOptionLi().data('index'), 10);
+ var newIndex = currIndex + amt;
+ return this._optionLis.eq(newIndex).trigger('mouseup');
+ },
+
+ _moveFocus: function(amt){
+ if(!isNaN(amt)){
+ var currIndex = parseInt(this._focusedOptionLi().data('index'), 10);
+ var newIndex = currIndex + amt;
+ }
+ else { var newIndex =
parseInt(this._optionLis.filter(amt).data('index'), 10); }
+
+ if(newIndex < 0){ newIndex = 0; }
+ if(newIndex > this._optionLis.size()-1){
+ newIndex = this._optionLis.size()-1;
+ }
+ this._focusedOptionLi().find('a:eq(0)').blur();
+ this._optionLis.eq(newIndex).find('a:eq(0)').focus();
+ },
+
+ _scrollPage: function(direction){
+ var numPerPage = Math.floor(this.list.outerHeight() /
this.list.find('li:first').outerHeight());
+ numPerPage = (direction == 'up') ? -numPerPage : numPerPage;
+ this._moveFocus(numPerPage);
},
_change: function(event, index) {