Böngésző független eseménykezelés keretrendszer nélkül 2
Legutóbbi bejegyzésem óta gondolkodtam, hogy hogyan lehetne még szebben, ugyanakkor nem túl nagy méretben megoldani a böngésző független eseménykezelést. Továbbra is a minimalitás a cél, de most bekerült az esemény eltávolítása is. És mindezt sikerült elérnem egy kicsi függvénytárban, ami YUI Compressor-ral minify-olva mindössze 1Kb.
/*! Copyright (c) 2010-2011 Peter (Poetro) Galiba MIT Licensed */
/**
* @fileoverview Browser independent basic event handling.
* @author Peter (Poetro) Galiba
*/
(function (window) {
/**
* Normalizáljuk az event objektumot.
*
* A normalizált tulajdonságok:
* - target
* - preventDefault
* - stopPropagation
*
* @param {Object} event
* Event objektum
* @returns {Element}
* Az esemény célpontja
*/
function normalizeEvent(event) {
var target;
if (!event) {
event = window.event;
}
if (event.target) {
target = event.target;
}
else if (event.srcElement) {
target = event.srcElement;
}
if (target && target.nodeType == 3) {
target = target.parentNode;
}
event.preventDefault = event.preventDefault || function () {
this.returnValue = false;
};
event.stopPropagation = event.stopPropagation || function () {
this.cancelBubble = true;
};
return target;
}
/**
* addEvent callback függvényének előkészítése.
*
* @param {Function} func
* A callback függvény.
* @returns {Function}
* Az új callback függvény.
*
* @see addEvent
*/
function prepareCallback(func) {
// Olyan függvényt állítunk elő amiben a this már az esemény célpontja.
return function (event) {
var target = normalizeEvent(event),
returnValue = func.call(target, event);
if (returnValue === false) {
event.preventDefault();
event.stopPropagation();
}
return returnValue;
};
}
/**
* Lekérdezi a megadott függvényhez tartozó callback függvényt.
*
* @param {Function} func
* A függvény, amihez kell a callback függvény.
* @param {String} [op]
* A művelet, amit esetleg végezni kell.
* A getCallback függvény karabantart egy listát a callback függvényekről.
* Ezt az op értékével a következőképpen lehet módosítani:
* - 'add' : hozzáadja a listához,
* - 'remove' : eltávolítja a listából.
*/
function getCallback(func, op) {
var gc = getCallback, fl, i, map, f, index = -1;
// Karbantartott `static` függvény lista.
if (!gc.fl) {
gc.fl = [];
}
fl = gc.fl;
// Végigmegyünk a listán, hogy megtaláljuk benne a függvényt.
for (i = fl.length - 1; i >= 0; i -= 1) {
map = fl[i];
if (map && map.original === func) {
index = i;
f = map.generated;
break;
}
}
if (op === 'remove') {
if (index !== -1) {
fl[ index ].counter -= 1;
if (fl[ index ].counter <= 0) {
delete fl[ index ];
}
}
}
else if (op === 'add') {
if (index !== -1) {
fl[ index ].counter += 1;
}
else {
f = prepareCallback(func);
fl[fl.length] = {
original : func,
generated : f,
counter : 1
};
}
}
return f;
}
/**
* Eltávolítja a megadott eseménykezelőt az elemről.
*
* @param {Element} elm
* A DOM elem, amiről el kell távolítani az eseményt.
* @param {String} evt
* Az esemény neve, például `click`.
* @param {Function} func
* A callback függvény, ami meghívódik amikor az esemény kiváltódik.
*/
this.removeEvent = function (elm, evt, func) {
var f = getCallback(func, 'remove'),
removeEventListener = elm.removeEventListener,
detachEvent = elm.detachEvent;
if (removeEventListener) {
removeEventListener.call(elm, evt, f, false);
}
else if (detachEvent) {
detachEvent.call(elm, 'on' + evt, f);
}
else {
elm['on' + evt] = null;
}
};
/**
* Hozzáadja a megadott eseménykezelőt az elemhez.
*
* @param {Element} elm
* A DOM elem, amihez hozzá kell adni az eseményt.
* @param {String} evt
* Az esemény neve, például `click`.
* @param {Function} func
* A callback függvény, ami meghívódik amikor az esemény kiváltódik.
*/
this.addEvent = function (elm, evt, func) {
var f = getCallback(func, 'add'),
addEventListener = elm.addEventListener,
attachEvent = elm.attachEvent;
if (addEventListener) {
addEventListener.call(elm, evt, f, false);
}
else if (attachEvent) {
attachEvent.call(elm, 'on' + evt, f);
}
else {
elm['on' + evt] = f;
}
};
}).call(this, this);