/**
* Mixes keyboard support into AutoCompleteList. By default, this module is not
* loaded for iOS and Android devices.
*
* @module autocomplete
* @submodule autocomplete-list-keys
*/
// keyCode constants.
var KEY_DOWN = 40,
KEY_ENTER = 13,
KEY_ESC = 27,
KEY_TAB = 9,
KEY_UP = 38;
function ListKeys() {
Y.before(this._unbindKeys, this, 'destructor');
Y.before(this._bindKeys, this, 'bindUI');
this._initKeys();
}
ListKeys.prototype = {
// -- Lifecycle Methods ----------------------------------------------------
/**
* Initializes keyboard command mappings.
*
* @method _initKeys
* @protected
* @for AutoCompleteList
*/
_initKeys: function () {
var keys = {},
keysVisible = {};
this._keyEvents = [];
// Register keyboard command handlers. _keys contains handlers that will
// always be called; _keysVisible contains handlers that will only be
// called when the list is visible.
keys[KEY_DOWN] = this._keyDown;
keysVisible[KEY_ENTER] = this._keyEnter;
keysVisible[KEY_ESC] = this._keyEsc;
keysVisible[KEY_TAB] = this._keyTab;
keysVisible[KEY_UP] = this._keyUp;
this._keys = keys;
this._keysVisible = keysVisible;
},
/**
* Binds keyboard events.
*
* @method _bindKeys
* @protected
*/
_bindKeys: function () {
this._keyEvents.push(this._inputNode.on(
Y.UA.gecko ? 'keypress' : 'keydown', this._onInputKey, this));
},
/**
* Unbinds keyboard events.
*
* @method _unbindKeys
* @protected
*/
_unbindKeys: function () {
while (this._keyEvents.length) {
this._keyEvents.pop().detach();
}
},
// -- Protected Methods ----------------------------------------------------
/**
* Called when the down arrow key is pressed.
*
* @method _keyDown
* @protected
*/
_keyDown: function () {
if (this.get('visible')) {
this._activateNextItem();
} else {
this.show();
}
},
/**
* Called when the enter key is pressed.
*
* @method _keyEnter
* @protected
*/
_keyEnter: function () {
this.selectItem();
},
/**
* Called when the escape key is pressed.
*
* @method _keyEsc
* @protected
*/
_keyEsc: function () {
this.hide();
},
/**
* Called when the tab key is pressed.
*
* @method _keyTab
* @protected
*/
_keyTab: function () {
var item;
if (this.get('tabSelect')) {
item = this.get('activeItem');
if (item) {
this.selectItem(item);
return true;
}
}
return false;
},
/**
* Called when the up arrow key is pressed.
*
* @method _keyUp
* @protected
*/
_keyUp: function () {
this._activatePrevItem();
},
// -- Protected Event Handlers ---------------------------------------------
/**
* Handles <code>inputNode</code> key events.
*
* @method _onInputKey
* @param {EventTarget} e
* @protected
*/
_onInputKey: function (e) {
var handler,
keyCode = e.keyCode;
this._lastInputKey = keyCode;
if (this.get('results').length) {
handler = this._keys[keyCode];
if (!handler && this.get('visible')) {
handler = this._keysVisible[keyCode];
}
if (handler) {
// A handler may return false to indicate that it doesn't wish
// to prevent the default key behavior.
if (handler.call(this, e) !== false) {
e.preventDefault();
}
}
}
}
};
Y.Base.mix(Y.AutoCompleteList, [ListKeys]);