I'd like to post some functions that proved useful for me.
a quick search showed that JQuery and Prototype already include such functionalities , so the intended audience is non-JQuery/Prototype users.
is this useful then to post such functions?
apply a function to a HTMLCollection (node-list)
originating from MDC's Array.forEach() code
example usage
assign an Event for each element of a node-list
example usage:
converting addEvent(elemen t, …) to element.addEven t(…)
one addEvent() function put into an object
a quick search showed that JQuery and Prototype already include such functionalities , so the intended audience is non-JQuery/Prototype users.
is this useful then to post such functions?
apply a function to a HTMLCollection (node-list)
originating from MDC's Array.forEach() code
Code:
// Firefox does not allow prototyping into the NodeList or HTMLCollection interface
// so their parent object has to be used
Object.prototype.applyForEach = function(fn)
{
if ("function" != typeof fn)
{
throw new TypeError();
}
var args = Array.prototype.slice.call(arguments, 1);
for (var i=0, len=this.length >>> 0; i<len; i++)
{
if (i in this)
{
fn.apply(this[i], args);
}
}
}
Code:
// it’s up to your imagination what foo() is doing…
document.getElementsByTagName("p").applyForEach(foo, "bar")
Code:
Object.prototype.addEventForEach = function(type, fn, cpt)
{
if (typeof fn != "function") {
throw new TypeError();
}
for (var i=0, len=this.length >>> 0; i<len; i++)
{
if (i in this)
{
// this[i].addEvent(type, fn, cpt);
Events._addEvent(this[i], type, fn, cpt);
}
}
}
Code:
// trigger a function by clicking on any table cell
document.getElementsByTagName("td").addEventForEach("click", doSmthWithTableCell);
Code:
HTMLElement.prototype.addEvent = function(type, fn, capture)
{
Events._addEvent(this, type, fn, capture);
}
Code:
// stripped off the inline comments
/**
* Crossbrowser event handling functions.
*
* A set of functions to easily attach and detach event handlers to HTML elements.
* These functions work around the shortcomings of the traditional method ( element.onevent = function; )
* where only 1 handler could be attached for a certain event on the object, and mimic the DOM level 2
* event methods addEventListener and removeEventListener for browsers that do not support these
* methods (e.g. Internet Explorer) without resorting to propriety methods such as attachEvent and detachEvent
* that have a whole set of their own shortcomings.
* Created as an entry for the 'contest' at quirksmode.org:
* http://www.quirksmode.org/blog/archives/2005/09/addevent_recodi.html
*
* @author Tino Zijdel ( crisp@xs4all.nl )
* @version 1.2
* @date 2005-10-21
*/
Events = function() {
/**
* [private] array_search
*
* Searches the array for a given value and returns the (highest) corresponding key if successful, -1 if not found.
*
* @param val The value to search for.
* @param arr The array to search in.
* @return (mixed) array index of val.
*/
function array_search(val, arr)
{
var i = arr.length;
while (i--)
{
if (arr[i] && arr[i] === val) break;
}
return i;
}
/**
* [private] IEEventHandler
*
* IE helper function to execute the attached handlers for events.
* Because of the way this helperfunction is attached to the object (using the DOM level 0 method)
* the 'this' keyword will correctely point to the element that the handler was defined on.
*
* @param e (optional) Event object, defaults to window.event object when not passed as argument (IE).
* @return (mixed)
*/
function IEEventHandler(e)
{
e = e || window.event;
var evTypeRef = '__' + e.type, retValue = true;
for (var i = 0, j = this[evTypeRef].length; i < j; i++)
{
if (this[evTypeRef][i])
{
if (Function.call)
{
retValue = this[evTypeRef][i].call(this, e) && retValue;
}
else
{
this.__fn = this[evTypeRef][i];
retValue = this.__fn(e) && retValue;
}
}
}
if (this.__fn)
{
try
{
delete this.__fn;
}
catch(e)
{
this.__fn = null;
}
}
return retValue;
}
return {
/**
* [public] addEvent
*
* Generic function to attach event listeners to HTML elements.
* This function does NOT use attachEvent but creates an own stack of function references
* in the DOM space of the element. This prevents closures and therefor possible memory leaks.
* Also because of the way the function references are stored they will get executed in the
* same order as they where attached - matching the behavior of addEventListener.
*
* @param obj The object to which the event should be attached.
* @param evType The eventtype, eg. 'click', 'mousemove' etcetera.
* @param fn The function to be executed when the event fires.
* @param useCapture (optional) Whether to use event capturing, or event bubbling (default).
* @return (void)
*/
_addEvent : function(obj, evType, fn, useCapture)
{
if (!useCapture) useCapture = false;
if (obj.addEventListener)
{
obj.addEventListener(evType, fn, useCapture);
}
else
{
if (useCapture)
{
alert('This browser does not support event capturing!');
}
else
{
var evTypeRef = '__' + evType;
if (obj[evTypeRef])
{
if (array_search(fn, obj[evTypeRef]) > -1) return;
}
else
{
obj[evTypeRef] = [];
if (obj['on'+evType])
{
obj[evTypeRef][0] = obj['on'+evType];
}
obj['on'+evType] = IEEventHandler;
}
obj[evTypeRef][obj[evTypeRef].length] = fn;
}
}
},
/**
* [public] removeEvent
*
* Generic function to remove previously attached event listeners.
*
* @param obj The object to which the event listener was attached.
* @param evType The eventtype, eg. 'click', 'mousemove' etcetera.
* @param fn The listener function.
* @param useCapture (optional) Whether event capturing, or event bubbling (default) was used.
* @return (void)
*/
_removeEvent : function(obj, evType, fn, useCapture)
{
if (!useCapture) useCapture = false;
if (obj.removeEventListener)
{
obj.removeEventListener(evType, fn, useCapture);
}
else
{
var evTypeRef = '__' + evType;
if (obj[evTypeRef])
{
var i = array_search(fn, obj[evTypeRef]);
if (i > -1)
{
try
{
delete obj[evTypeRef][i];
}
catch(e)
{
obj[evTypeRef][i] = null;
}
}
}
}
},
/**
* [public] loading
*
* simplifies the window.onload calls
*
* @param callback the function called onload
* @return (void)
*/
loading : function(callback)
{
Events._addEvent(window, "load", callback);
}
};
}();
Comment