218 lines
7.3 KiB
JavaScript
218 lines
7.3 KiB
JavaScript
/*! jQuery UI Virtual Keyboard Navigation v1.6.1 *//*
|
|
* for Keyboard v1.18+ only (updated 7/7/2015)
|
|
*
|
|
* By Rob Garrison (aka Mottie & Fudgey)
|
|
* Licensed under the MIT License
|
|
*
|
|
* Use this extension with the Virtual Keyboard to navigate
|
|
* the virtual keyboard keys using the arrow, page, home and end keys
|
|
* Using this extension WILL prevent keyboard navigation inside of all
|
|
* input and textareas
|
|
*
|
|
* Requires:
|
|
* jQuery
|
|
* Keyboard plugin : https://github.com/Mottie/Keyboard
|
|
*
|
|
* Setup:
|
|
* $('.ui-keyboard-input')
|
|
* .keyboard(options)
|
|
* .addNavigation();
|
|
*
|
|
* // or if targeting a specific keyboard
|
|
* $('#keyboard1')
|
|
* .keyboard(options) // keyboard plugin
|
|
* .addNavigation(); // this keyboard extension
|
|
*
|
|
*/
|
|
/*jshint browser:true, jquery:true, unused:false */
|
|
/*global require:false, define:false, module:false */
|
|
;(function(factory) {
|
|
if (typeof define === 'function' && define.amd) {
|
|
define(['jquery'], factory);
|
|
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
|
module.exports = factory(require('jquery'));
|
|
} else {
|
|
factory(jQuery);
|
|
}
|
|
}(function($) {
|
|
'use strict';
|
|
$.keyboard = $.keyboard || {};
|
|
|
|
$.keyboard.navigationKeys = {
|
|
// all keys
|
|
toggle : 112, // toggle key; F1 = 112 (event.which value for function 1 key)
|
|
enter : 13,
|
|
pageup : 33,
|
|
pagedown : 34,
|
|
end : 35,
|
|
home : 36,
|
|
left : 37,
|
|
up : 38,
|
|
right : 39,
|
|
down : 40,
|
|
// move caret WITH navigate toggle active
|
|
caretrt : 45, // Insert key
|
|
caretlt : 46, // delete key
|
|
|
|
// ** custom navigationKeys functions **
|
|
// move caret without navigate toggle active
|
|
caretright : function(kb){
|
|
$.keyboard.keyaction.right(kb);
|
|
},
|
|
caretleft : function(kb){
|
|
$.keyboard.keyaction.left(kb);
|
|
}
|
|
|
|
};
|
|
|
|
$.fn.addNavigation = function(options){
|
|
return this.each(function(){
|
|
// make sure a keyboard is attached
|
|
var o, k,
|
|
base = $(this).data('keyboard'),
|
|
opts = base.options,
|
|
defaults = {
|
|
position : [0,0], // set start position [row-number, key-index]
|
|
toggleMode : false, // true = navigate the virtual keyboard, false = navigate in input/textarea
|
|
focusClass : 'hasFocus',// css class added when toggle mode is on
|
|
toggleKey : null // defaults to $.keyboard.navigationKeys.toggle value
|
|
},
|
|
kbevents = $.keyboard.events;
|
|
if (!base) { return; }
|
|
|
|
base.navigation_options = o = $.extend({}, defaults, options);
|
|
base.navigation_keys = k = $.extend({}, $.keyboard.navigationKeys);
|
|
base.navigation_namespace = base.namespace + 'Nav';
|
|
base.extensionNamespace.push( base.navigation_namespace );
|
|
|
|
// save navigation settings - disabled when the toggled
|
|
base.saveNav = [ base.options.tabNavigation, base.options.enterNavigation ];
|
|
base.allNavKeys = $.map(k, function(v,i){ return v; });
|
|
|
|
// Setup
|
|
base.navigation_init = function(){
|
|
var kbcss = $.keyboard.css;
|
|
base.$keyboard.toggleClass(o.focusClass, o.toggleMode)
|
|
.find('.' + kbcss.keySet + ':visible')
|
|
.find('.' + kbcss.keyButton + '[data-pos="' + o.position[0] + ',' + o.position[1] + '"]')
|
|
.addClass(opts.css.buttonHover);
|
|
|
|
base.$preview
|
|
.unbind(base.navigation_namespace)
|
|
.bind('keydown' + base.navigation_namespace,function(e){
|
|
return base.checkKeys(e.which);
|
|
});
|
|
|
|
};
|
|
|
|
base.checkKeys = function(key, disable){
|
|
if (typeof(key) === "undefined") {
|
|
return;
|
|
}
|
|
var k = base.navigation_keys,
|
|
kbcss = $.keyboard.css;
|
|
if (key === ( o.toggleKey || k.toggle ) || disable) {
|
|
o.toggleMode = (disable) ? false : !o.toggleMode;
|
|
base.options.tabNavigation = (o.toggleMode) ? false : base.saveNav[0];
|
|
base.options.enterNavigation = (o.toggleMode) ? false : base.saveNav[1];
|
|
}
|
|
base.$keyboard.toggleClass(o.focusClass, o.toggleMode);
|
|
if ( o.toggleMode && key === k.enter ) {
|
|
base.$keyboard
|
|
.find('.' + kbcss.keySet + ':visible')
|
|
.find('.' + kbcss.keyButton + '[data-pos="' + o.position[0] + ',' + o.position[1] + '"]')
|
|
.trigger(kbevents.kbRepeater);
|
|
return false;
|
|
}
|
|
if ( o.toggleMode && $.inArray(key, base.allNavKeys) >= 0 ) {
|
|
base.navigateKeys(key);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
base.navigateKeys = function(key, row, indx){
|
|
indx = typeof indx === 'number' ? indx : o.position[1];
|
|
row = typeof row === 'number' ? row : o.position[0];
|
|
var kbcss = $.keyboard.css,
|
|
vis = base.$keyboard.find('.' + kbcss.keySet + ':visible'),
|
|
maxRow = vis.find('.' + kbcss.endRow).length - 1,
|
|
maxIndx = vis.find('.' + kbcss.keyButton + '[data-pos^="' + row + ',"]').length - 1,
|
|
p = base.last,
|
|
l = base.$preview.val().length,
|
|
k = base.navigation_keys;
|
|
|
|
switch(key){
|
|
case k.pageup : row = 0; break; // pageUp
|
|
case k.pagedown : row = maxRow; break; // pageDown
|
|
case k.end : indx = maxIndx; break; // End
|
|
case k.home : indx = 0; break; // Home
|
|
case k.left : indx += (indx > 0) ? -1 : 0; break; // Left
|
|
case k.up : row += (row > 0) ? -1 : 0; break; // Up
|
|
case k.right : indx += 1; break; // Right
|
|
case k.down : row += (row + 1 > maxRow) ? 0 : 1; break; // Down
|
|
case k.caretrt : p.start++; break; // caret right
|
|
case k.caretlt : p.start--; break; // caret left
|
|
}
|
|
|
|
// move caret
|
|
if (key === k.caretrt || key === k.caretlt) {
|
|
p.start = p.start < 0 ? 0 : p.start > l ? l : p.start;
|
|
base.last.start = base.last.end = p.end = p.start;
|
|
$.keyboard.caret( base.$preview, base.last );
|
|
}
|
|
|
|
// get max index of new row
|
|
maxIndx = vis.find('.' + kbcss.keyButton + '[data-pos^="' + row + ',"]').length - 1;
|
|
if (indx > maxIndx) { indx = maxIndx; }
|
|
|
|
vis.find('.' + opts.css.buttonHover).removeClass(opts.css.buttonHover);
|
|
vis.find('.' + kbcss.keyButton + '[data-pos="' + row + ',' + indx + '"]').addClass(opts.css.buttonHover);
|
|
o.position = [ row, indx ];
|
|
};
|
|
|
|
// visible event is fired before this extension is initialized, so check!
|
|
if (base.options.alwaysOpen && base.isVisible) {
|
|
base.$keyboard.find('.' + opts.css.buttonHover).removeClass(opts.css.buttonHover);
|
|
base.navigation_init();
|
|
}
|
|
// navigation bindings
|
|
base.$el
|
|
.unbind(base.navigation_namespace)
|
|
.bind(kbevents.kbVisible, function(){
|
|
base.$keyboard.find('.' + opts.css.buttonHover).removeClass(opts.css.buttonHover);
|
|
base.navigation_init();
|
|
})
|
|
.bind(kbevents.kbInactive + ' ' + kbevents.kbHidden, function(e){
|
|
base.checkKeys(e.which, true); // disable toggle mode & revert navigation options
|
|
})
|
|
.bind(kbevents.kbKeysetChange, function(){
|
|
base.navigateKeys(null);
|
|
})
|
|
.bind('navigate navigateTo', function(e, row, indx){
|
|
var key;
|
|
// no row given, check if it's a navigation key or keyaction
|
|
row = isNaN(row) ? row.toLowerCase() : row;
|
|
if (row in base.navigation_keys) {
|
|
key = base.navigation_keys[row];
|
|
if (isNaN(key) && key in $.keyboard.keyaction) {
|
|
// defined navigation_keys string name is a defined keyaction
|
|
$.keyboard.keyaction[key]( base, this, e );
|
|
} else if ($.isFunction(key)) {
|
|
// custom function defined in navigation_keys
|
|
key(base);
|
|
} else {
|
|
// key (e.which value) is defined in navigation_keys
|
|
base.checkKeys(key);
|
|
}
|
|
} else if ( typeof row === 'string' && row in $.keyboard.keyaction ) {
|
|
// navigate called directly with a keyaction name
|
|
$.keyboard.keyaction[row]( base, this, e );
|
|
} else {
|
|
base.navigateKeys(null, row, indx);
|
|
}
|
|
});
|
|
|
|
});
|
|
};
|
|
|
|
}));
|