govlab-styleguide
Version:
A styleguide / lightweight frontend framework for GovLab websites
116 lines (101 loc) • 4.14 kB
JavaScript
/*******************************************
* *
* This util was created by Marius Olbertz *
* Please thank Marius on GitHub /owlbertz *
* or the web http://www.mariusolbertz.de/ *
* *
******************************************/
!function($, Foundation){
'use strict';
Foundation.Keyboard = {};
var keyCodes = {
9: 'TAB',
13: 'ENTER',
27: 'ESCAPE',
32: 'SPACE',
37: 'ARROW_LEFT',
38: 'ARROW_UP',
39: 'ARROW_RIGHT',
40: 'ARROW_DOWN'
};
/*
* Constants for easier comparing.
* Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE
*/
var keys = (function(kcs) {
var k = {};
for (var kc in kcs) k[kcs[kc]] = kcs[kc];
return k;
})(keyCodes);
Foundation.Keyboard.keys = keys;
/**
* Parses the (keyboard) event and returns a String that represents its key
* Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE
* @param {Event} event - the event generated by the event handler
* @return String key - String that represents the key pressed
*/
var parseKey = function(event) {
var key = keyCodes[event.which || event.keyCode] || String.fromCharCode(event.which).toUpperCase();
if (event.shiftKey) key = 'SHIFT_' + key;
if (event.ctrlKey) key = 'CTRL_' + key;
if (event.altKey) key = 'ALT_' + key;
return key;
};
Foundation.Keyboard.parseKey = parseKey;
// plain commands per component go here, ltr and rtl are merged based on orientation
var commands = {};
/**
* Handles the given (keyboard) event
* @param {Event} event - the event generated by the event handler
* @param {String} component - Foundation component's name, e.g. Slider or Reveal
* @param {Objects} functions - collection of functions that are to be executed
*/
var handleKey = function(event, component, functions) {
var commandList = commands[component],
keyCode = parseKey(event),
cmds,
command,
fn;
if (!commandList) return console.warn('Component not defined!');
if (typeof commandList.ltr === 'undefined') { // this component does not differentiate between ltr and rtl
cmds = commandList; // use plain list
} else { // merge ltr and rtl: if document is rtl, rtl overwrites ltr and vice versa
if (Foundation.rtl()) cmds = $.extend({}, commandList.ltr, commandList.rtl);
else cmds = $.extend({}, commandList.rtl, commandList.ltr);
}
command = cmds[keyCode];
fn = functions[command];
if (fn && typeof fn === 'function') { // execute function if exists
fn.apply();
if (functions.handled || typeof functions.handled === 'function') { // execute function when event was handled
functions.handled.apply();
}
} else {
if (functions.unhandled || typeof functions.unhandled === 'function') { // execute function when event was not handled
functions.unhandled.apply();
}
}
};
Foundation.Keyboard.handleKey = handleKey;
/**
* Finds all focusable elements within the given `$element`
* @param {jQuery} $element - jQuery object to search within
* @return {jQuery} $focusable - all focusable elements within `$element`
*/
var findFocusable = function($element) {
return $element.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').filter(function() {
if (!$(this).is(':visible') || $(this).attr('tabindex') < 0) { return false; } //only have visible elements and those that have a tabindex greater or equal 0
return true;
});
};
Foundation.Keyboard.findFocusable = findFocusable;
/**
* Returns the component name name
* @param {Object} component - Foundation component, e.g. Slider or Reveal
* @return String componentName
*/
var register = function(componentName, cmds) {
commands[componentName] = cmds;
};
Foundation.Keyboard.register = register;
}(jQuery, window.Foundation);