jsbeans

jsbeans  1.0.0

jsbeans > jsbeans > events.js (source view)
Search:
 
Filters
/*!
 * Copyright (c) 2009 Francesco Mele jsbeans@francescomele.com
 *
 * This Software is licenced under the LGPL Licence (GNU Lesser General 
 * Public License).
 * In addition to the LGPL Licence the Software is subject to the 
 * following conditions:
 * 
 * 	i	every modification must be public and comunicated to the Author
 * 	ii	every "jsbean" added to this library must be self consistent 
 * 		except for the dependence from jsbeans-x.x.x.js
 * 	iii	copyright notice and this permission notice shall be included 
 * 		in all copies or substantial portions of the Software
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * A collection of utilities for managing events
 * @namespace jsbeans
 * @class events
 * @static
 */
jsbeans.events = {
	/**
	 * @property an Array of managed events to flush on window unload or to get on object event remove.
	 * @type Array
	 * @private
	 * @static
	 */
	_HANDLER_CACHE: new Array(),
	/**
	 * A way to make DOM Object dinamic attaching functions fired at given event.
	 * @method addHandler
	 * @param element {DOM} the DOM Object on which the events will be fired
	 * @param name {String} the name of the event (i.e. 'click') <strong>without</strong> 'on'
	 * @param handler {Function} the closure fired on given event
	 * @static
	 */
	addHandler: function(element, name, handler) {
		jsbeans.events._HANDLER_CACHE.push({e: element, n: name, h: handler});
		if (element.addEventListener) {
			element.addEventListener(name, handler, false);
	    } 
		else if (element.attachEvent) {
			element["e" + name + handler] = handler;
			element[name + handler] = function() {
				element["e" + name + handler](window.event);
			};
	    	element.attachEvent('on' + name, element[name + handler]);
	    }
	},
	/**
	 * A way to make DOM Object dinamic attaching functions fired at given event.<br/>
	 * Internally it calls <code class="methd">jsbeans.events.addHandler</code>
	 * @method bind
	 * @param element {DOM} the DOM Object on which the events will be fired
	 * @param name {String} the name of the event (i.e. 'click') <strong>without</strong> 'on'
	 * @param handler {Function} the closure fired on given event
	 * @static
	 * @see jsbeans.events.addHandler
	 */
	bind: function(element, name, handler) {
		jsbeans.events.addHandler(element, name, handler);
	},
	/**
	 * Removes a previously attached event.
	 * @method removeHandler
	 * @param element {DOM} the DOM Object on which the events will be fired
	 * @param name {String} the name of the event (i.e. 'click') <strong>without</strong> 'on'
	 * @param handler {Function} the closure fired on given event
	 * @static
	 */
	removeHandler: function(element, name, handler) {
		if (handler == null) {
			for (var i = 0, hc; hc = jsbeans.events._HANDLER_CACHE[i]; i++) {
				if (hc.e == element && hc.n == name) {
					handler = hc.h;
					break;
				}
			}
		}
	    if (element.removeEventListener) {
	    	element.removeEventListener(name, handler, false);
	    } 
	    else if (element.detachEvent) {
	    	element.detachEvent('on' + name, element[name + handler]);
	    }
	    var newCache = new Array();
		for (var i = 0, hc; hc = jsbeans.events._HANDLER_CACHE[i]; i++) {
			if (hc.e != element && hc.n != name) {
				newCache.push(hc);
			}
		}
		jsbeans.events._HANDLER_CACHE = newCache;
		element = null;
	},
	/**
	 * Removes a previously attached event.<br/>
	 * Internally it calls <code class="methd">jsbeans.events.removeHandler</code>
	 * @method unbind
	 * @param element {DOM} the DOM Object on which the events will be fired
	 * @param name {String} the name of the event (i.e. 'click') <strong>without</strong> 'on'
	 * @param handler {Function} the closure fired on given event
	 * @static
	 * @see jsbeans.events.removeHandler
	 */
	unbind: function(element, name, handler) {
		jsbeans.events.removeHandler(element, name, handler);
	},
	/**
	 * Removes all previously attached events.
	 * @method flush
	 * @static
	 */
	flush: function() {
		for (var i = 0, hc; hc = jsbeans.events._HANDLER_CACHE[i]; i++) {
		    if (hc.e.removeEventListener) {
		    	hc.e.removeEventListener(hc.n, hc.h, false);
		    } 
		    else if (hc.e.detachEvent) {
		    	hc.e.detachEvent('on' + hc.n, hc.e[hc.n + hc.h]);
		    }
			hc.e = null;
		}
	},
	/**
	 * Creates a shortcut, also known as key binding.<br/>
	 * <span class="fixme">FIXME</span>: due to parsing problem it's not possible to bind backslash ('\')
	 * @method shortcut
	 * @param shortcutName {String} the shortcut. Ex.: 'CRTL+U'
	 * @param callback {Function} the function fired on pressing given <code class="param">shortcutName</code>
	 * @param [options] {JSON}
	 * <pre>
	 * propagate: a_boolean, // if true it enables firing other events (it does not call cancelBubble), default false
	 * target: DOM_or_String // a DOM Object (or its id) on which the shortcut will be associated
	 * </pre>
	 * @static
	 * @author Francesco Mele
	 * @credits unknown (code found on the net)
	 */
	shortcut: function(shortcut, callback /*,options*/) {
		var options = arguments[2] || {};

		var propagate = options.propagate || false;
		var type = options.type || "keydown";

		var obj = options.target || document;
		if (typeof(options.target) == 'string') {
			obj = document.getElementById(options.target);
		}

		var _function = function(e) {
			e = e || window.event;
			var code;
			if (e.keyCode) {
				code = e.keyCode;
			} 
			else if (e.which) {
				code = e.which;
			}
			var character = String.fromCharCode(code).toLowerCase();

			var keys = shortcut.toLowerCase().split("+");
			var kp = 0;
			var shift_nums = {
							"`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^",
							"7":"&", "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":",
							"'":'"', ",":"<", ".":">", "/":"?"
			};
			var special_keys = {'esc':27, 'escape':27, 'tab':9, 'space':32, 'return':13, 'enter':13,
							'backspace':8, 'scrolllock':145, 'scroll_lock':145, 'scroll':145,
							'capslock':20, 'caps_lock':20, 'caps':20, 'numlock':144, 'num_lock':144,
							'num':144, 'pause':19, 'break':19, 'insert':45, 'home':36, 'delete':46,
							'end':35, 'pageup':33, 'page_up':33, 'pu':33, 'pagedown':34, 'page_down':34,
							'pd':34, 'left':37, 'up':38, 'right':39, 'down':40, 'f1':112, 'f2':113,
							'f3':114, 'f4':115, 'f5':116, 'f6':117, 'f7':118, 'f8':119, 'f9':120,
							'f10':121, 'f11':122, 'f12':123
			};
			for (var i = 0; k = keys[i], i < keys.length; i++) {
				if (k == 'ctrl' || k == 'control') {
					if (e.ctrlKey) {
						kp++;
					}
				} 
				else if (k ==  'shift') {
					if (e.shiftKey) {
						kp++;
					}
				} 
				else if (k == 'alt') {
					if (e.altKey) {
						kp++;
					}
				} 
				else if (k.length > 1) {
					if (special_keys[k] == code) {
						kp++;
					}
				} 
				else {
					if (character == k) {
						kp++;
					} 
					else {
						if (shift_nums[character] && e.shiftKey) {
							character = shift_nums[character]; 
							if (character == k) {
								kp++;
							}
						}
					}
				}
			}
			if (kp == keys.length) {
				callback(e);
				if (!options.propagate) {
					e.cancelBubble = true;
					e.returnValue = false;
					if (e.stopPropagation) {
						e.stopPropagation();
						e.preventDefault();
					}
					try {
						window.event.keyCode = 505;
					} 
					catch(e) {}
					return false;
				}
			}
		};
		jsbeans.events.addHandler(obj, type, _function);
	},
	/**
	 * Returns the DOM Object attached on given {@param} <code class="param">event</code>
	 * @for events
	 * @method getEventTarget
	 * @param event {event} 
	 * @return {DOM} the DOM Object attached on event
	 * @static
	 */
	getEventTarget: function(e) {
		try {
			e = e || event;
			var object = e.srcElement || e.target;
			if (object != null) {
				return object;
			}
		} 
		catch(e) {
			return null;
		}
	},
	/**
	 * Returns the DOM Object attached on given {@param} <code class="param">event</code>.<br/>
	 * Internally it calls <code class="methd">jsbeans.events.getEventTarget</code>
	 * @for events
	 * @method getTarget
	 * @param event {event} 
	 * @return {DOM} the DOM Object attached on event
	 * @static
	 * @see jsbeans.events.getEventTarget
	 */
	getTarget: function(e) {
		return jsbeans.events.getEventTarget(e);
	}
};

/**
 * @config Removes alla events on window unload. It prevents memory leaks.
 * @private
 */
jsbeans.events.addHandler(window, "unload", jsbeans.events.flush);

Copyright © 2016 Francesco Mele. All rights reserved.