Skip to content

Commit 5df784f

Browse files
committed
added sequencial typeahead as the default option and left repeated typeahead as an option. added the typeahead attribute for options. added back typeahead for open menus.
1 parent 5fd470e commit 5df784f

File tree

1 file changed

+65
-23
lines changed

1 file changed

+65
-23
lines changed

ui/jquery.ui.selectmenu.js

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ $.widget("ui.selectmenu", {
1717
eventPrefix: "selectmenu",
1818
options: {
1919
transferClasses: true,
20+
typeAhead: "sequential",
2021
style: 'dropdown',
2122
positionOptions: {
2223
my: "left top",
@@ -37,10 +38,10 @@ $.widget("ui.selectmenu", {
3738
var self = this, o = this.options;
3839

3940
// set a default id value
40-
var selectmenuId = this.element.attr('id') || 'ui-selectmenu-' + Math.random().toString(16).slice(2, 10);
41+
this.selectmenuId = this.element.attr('id') || 'ui-selectmenu-' + Math.random().toString(16).slice(2, 10);
4142

4243
//quick array of button and menu id's
43-
this.ids = [selectmenuId + '-' + 'button', selectmenuId + '-' + 'menu'];
44+
this.ids = [this.selectmenuId + '-' + 'button', this.selectmenuId + '-' + 'menu'];
4445

4546
//define safe mouseup for future toggling
4647
this._safemouseup = true;
@@ -206,6 +207,7 @@ $.widget("ui.selectmenu", {
206207
break;
207208
default:
208209
ret = true;
210+
self._typeAhead(event.keyCode,'focus');
209211
break;
210212
}
211213
return ret;
@@ -229,6 +231,7 @@ $.widget("ui.selectmenu", {
229231
text: self._formatText($(this).text()),
230232
selected: $(this).attr('selected'),
231233
classes: $(this).attr('class'),
234+
typeahead: $(this).attr('typeahead'),
232235
parentOptGroup: $(this).parent('optgroup').attr('label'),
233236
bgImage: o.bgImage.call($(this))
234237
});
@@ -242,7 +245,8 @@ $.widget("ui.selectmenu", {
242245

243246
//write li's
244247
for (var i = 0; i < selectOptionData.length; i++) {
245-
var thisLi = $('<li role="presentation"><a href="#" tabindex="-1" role="option" aria-selected="false">'+ selectOptionData[i].text +'</a></li>')
248+
249+
var thisLi = $('<li role="presentation"><a href="#" tabindex="-1" role="option" aria-selected="false"'+ (selectOptionData[i].typeahead ? ' typeahead="' + selectOptionData[i].typeahead + '"' : '' ) + '>'+ selectOptionData[i].text +'</a></li>')
246250
.data('index',i)
247251
.addClass(selectOptionData[i].classes)
248252
.data('optionClasses', selectOptionData[i].classes|| '')
@@ -391,29 +395,67 @@ $.widget("ui.selectmenu", {
391395
$.Widget.prototype.destroy.apply(this, arguments);
392396
},
393397
_typeAhead: function(code, eventType){
394-
var self = this;
395-
//define self._prevChar if needed
396-
if (!self._prevChar){ self._prevChar = ['',0]; }
397-
var C = String.fromCharCode(code);
398+
var self = this, focusFound = false, C = String.fromCharCode(code);
398399
c = C.toLowerCase();
399-
var focusFound = false;
400-
function focusOpt(elem, ind){
401-
focusFound = true;
402-
$(elem).trigger(eventType);
403-
self._prevChar[1] = ind;
404-
}
405-
this.list.find('li a').each(function(i){
406-
if(!focusFound){
407-
var thisText = $(this).text();
408-
if( thisText.indexOf(C) == 0 || thisText.indexOf(c) == 0){
409-
if(self._prevChar[0] == C){
410-
if(self._prevChar[1] < i){ focusOpt(this,i); }
411-
}
412-
else{ focusOpt(this,i); }
400+
401+
if (self.options.typeAhead == 'sequential') {
402+
// clear the timeout so we can use _prevChar
403+
window.clearTimeout('ui.selectmenu-' + self.selectmenuId);
404+
405+
// define our find var
406+
var find = typeof(self._prevChar) == 'undefined' ? '' : self._prevChar.join('');
407+
408+
function focusOptSeq(elem, ind, char){
409+
focusFound = true;
410+
$(elem).trigger(eventType);
411+
typeof(self._prevChar) == 'undefined' ? self._prevChar = [char] : self._prevChar[self._prevChar.length] = char;
412+
}
413+
this.list.find('li a').each(function(i) {
414+
if (!focusFound) {
415+
// allow the typeahead attribute on the option tag for a more specific lookup
416+
var thisText = $(this).attr('typeahead') || $(this).text();
417+
if (thisText.indexOf(find+C) == 0) {
418+
focusOptSeq(this,i, C)
419+
} else if (thisText.indexOf(find+c) == 0) {
420+
focusOptSeq(this,i,c)
421+
}
413422
}
423+
});
424+
425+
// if we didnt find it clear the prevChar
426+
if (!focusFound) {
427+
//self._prevChar = undefined
414428
}
415-
});
416-
this._prevChar[0] = C;
429+
430+
// set a 1 second timeout for sequenctial typeahead
431+
// keep this set even if we have no matches so it doesnt typeahead somewhere else
432+
window.setTimeout(function(el) {
433+
el._prevChar = undefined;
434+
}, 1000, self);
435+
436+
} else {
437+
//define self._prevChar if needed
438+
if (!self._prevChar){ self._prevChar = ['',0]; }
439+
440+
var focusFound = false;
441+
function focusOpt(elem, ind){
442+
focusFound = true;
443+
$(elem).trigger(eventType);
444+
self._prevChar[1] = ind;
445+
}
446+
this.list.find('li a').each(function(i){
447+
if(!focusFound){
448+
var thisText = $(this).text();
449+
if( thisText.indexOf(C) == 0 || thisText.indexOf(c) == 0){
450+
if(self._prevChar[0] == C){
451+
if(self._prevChar[1] < i){ focusOpt(this,i); }
452+
}
453+
else{ focusOpt(this,i); }
454+
}
455+
}
456+
});
457+
this._prevChar[0] = C;
458+
}
417459
},
418460
// returns some usefull information, called by callbacks only
419461
_uiHash: function(){

0 commit comments

Comments
 (0)