We use cookies to make our website more effective. By using our website you agree to our privacy policy.

Source: keys.js

/**
 * keys.js is part of Aloha Editor project http://www.alohaeditor.org
 *
 * Aloha Editor ● JavaScript Content Editing Library
 * Copyright (c) 2010-2015 Gentics Software GmbH, Vienna, Austria.
 * Contributors http://www.alohaeditor.org/docs/contributing.html
 *
 * @see:
 * https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html
 *
 * @todo:
 * consider https://github.com/nostrademons/keycode.js/blob/master/keycode.js
 * @namespace keys
 */
define([
	'maps',
	'strings',
	'boundaries'
], function (
	Maps,
	Strings,
	Boundaries
) {
	'use strict';

	var CODE_KEY = {
		8  : 'backspace',
		9  : 'tab',
		12 : 'f1',
		13 : 'enter',
		16 : 'shift',
		17 : 'ctrl',
		18 : 'alt',
		20 : 'capslock',
		23 : 'end',
		24 : 'home',
		27 : 'escape',
		32 : 'space',
		33 : 'pageUp',
		34 : 'pageDown',
		37 : 'left',
		38 : 'up',
		39 : 'right',
		40 : 'down',
		46 : 'delete',
		65 : 'selectAll',
		66 : 'bold',
		73 : 'italic',
		85 : 'underline',
		90 : 'undo',
		91 : 'meta'
	};

	/**
	 * A map of key names to their keycode.
	 *
	 * @type {Object.<string, number>}
	 * @memberOf keys
	 */
	var CODES = {};
	Maps.forEach(CODE_KEY, function (current, index) {
		CODES[current] = parseInt(index, 10);
	});

	/**
	 * Arrow keys
	 *
	 * @type {Object.<number, string>}
	 * @memberOf keys
	 */
	var ARROWS = {
		37 : 'left',
		38 : 'up',
		39 : 'right',
		40 : 'down'
	};

	/**
	 * Returns a string of all meta keys for the given event.
	 *
	 * @private
	 * @param  {Event} event
	 * @return {string}
	 */
	function metaKeys(event) {
		var meta = [];
		if (event.altKey && (CODES['alt'] !== event.which)) {
			meta.push('alt');
		}
		if (event.ctrlKey && (CODES['ctrl'] !== event.which)) {
			meta.push('ctrl');
		}
		if (event.metaKey) {
			meta.push('meta');
		}
		if (event.shiftKey && (CODES['shift'] !== event.which)) {
			meta.push('shift');
		}
		return meta.join('+');
	}

	var EVENTS = {
		'keyup'    : true,
		'keydown'  : true,
		'keypress' : true
	};

	/**
	 * Provides meta, keycode
	 *
	 * @param  {!AlohaEvent} event
	 * @return {AlohaEvent}
	 * @memberOf keys
	 */
	function middleware(event) {
		var keys = parseKeys(event.nativeEvent);
		event.meta = keys.meta;
		event.keycode = event.keycode || keys.keycode;
		return event;
	}

	/**
	 * Parses keys for a browser event. Will return an object as follows:
	 *
	 * <pre>
	 * {
	 *     meta    : 'cmd+shift', // active meta keys
	 *     keycode : 32,          // currently active keycode
	 *     key     : 'space',     // associated key
	 *     char    : ''           // corresponding lowercase character key
	 * }
	 * </pre>
	 *
	 * @param  {!Event} event
	 * @return {Object.<string, *>}
	 * @memberOf keys
	 */
	function parseKeys(event) {
		return {
			meta    : metaKeys(event),
			keycode : event.which,
			key     : CODE_KEY[event.which],
			chr     : String.fromCharCode(event.which).toLowerCase()
		};
	}

	/**
	 * Goes through the shortcutHandlers object to find a shortcutHandler that
	 * matches the pressed meta keys along with the provided keycode. The
	 * shortcutHandler array must be structured as follows:
	 *
	 * <pre>
	 * // add a shortcut handler for meta+esc on keydown
	 * shortcutHandlers = {
	 *     'meta+escape'  : function () {},
	 *     'meta+shift+b' : function () {}
	 * }
	 * </pre>
	 *
	 * The order of meta keys in the shortcutHandlers array MUST be in
	 * alphabetical order, as provided by
	 *
	 * @see Keys.parseKeys
	 * @param  {!string}  meta
	 * @param  {!integer} keycode
	 * @param  {!Object}  shortcutHandlers
	 * @return {*} null if no handler could be found
	 * @memberOf keys
	 */
	function shortcutHandler(meta, keycode, shortcutHandlers) {
		// Try to resolve special keys outside the 40 (delete) to 91 (meta)
		// range. This range might need tweaking!
		var key = keycode <= 46 || keycode >= 91
		        ? CODE_KEY[keycode] || keycode
		        : String.fromCharCode(keycode).toLowerCase();
		return shortcutHandlers[meta ? meta + '+' + key : key]
		    || shortcutHandlers['*+' + key]
		    || null;
	}

	return {
		CODES           : CODES,
		EVENTS          : EVENTS,
		ARROWS          : ARROWS,
		middleware      : middleware,
		shortcutHandler : shortcutHandler,
		parseKeys       : parseKeys
	};
});
comments powered by Disqus