/*

	filename:	/js/evt.js
	version:	1.3 - 2007-02-22 - mkr

	author:		martin (dot) krause (at) gpm (dot) de 

*/

/*
	1.3 - mkr: added _flush on .remove()
	1.2 - mkr: added cache._remove()
	1.1 - mkr: fixed minor bugs
*/
/*!
@function evt()
@abstract constructor
*/

function evt () {
	if(!self) {this.self = this;}
	self._cachedEvts = [];
}

/*!
@function evt.add(_el, _evt, _fn)
@param 	_el: element to add eventhandler 
		_evt: type of eventhandler
		_fn: function that should be called 
@abstract adding eventhanlder (_evt) calling function (_fn) on element (_el). using even._cache to prevent memory leaks
*/
evt.prototype.add = function(_el,_evt,_fn) {
	// moz
	if (_el.addEventListener) {
		_el.addEventListener(_evt,_fn,false);
		evt._cache.add(_el, _evt,_fn);
	}
	// ie 
	else if (_el.attachEvent) {
		_el["e"+_evt+_fn] = _fn;
		_el[_evt+_fn] = function() { _el["e"+_evt+_fn]( window.event ); }
		_el.attachEvent( "on"+_evt, _el[_evt+_fn] );
		evt._cache.add(_el, _evt,_fn);
	}
	else {
		_el["on"+_evt] = _el["e"+_evt+_fn];
	}
}

/*!
@function evt.remove(_el, _evt,_fn,_flush)
@param 	_el: element to add eventhandler 
		_evt: type of eventhandler
		_fn: function that should be called 
		_flush: are we're flushing the whole cache?
@abstract removing eventhanlder (_evt) calling function (_fn) on element (_el).
*/
evt.prototype.remove = function (_el,_evt,_fn,_flush){
		var _flush = _flush || false;
		// moz
		if(_el.removeEventListener){
			_el.removeEventListener(_evt,_fn,false);
			if (!_flush) { evt._cache.remove(_el, _evt,_fn);}
		};
		// ie
		if(_el.detachEvent){
			_el.detachEvent( "on"+_evt,_el[_evt+_fn] );
			_el[_evt+_fn] = null;
			_el["e"+_evt+_fn] = null;
			if (!_flush) { evt._cache.remove(_el, _evt,_fn);}
		};
		if(_evt.substring(0, 2) != 'on'){
			_evt = 'on' + _evt;
		};
		_el[_evt] = null;
}

/*!
@function evt._cache()
@abstract constructor
*/
evt.prototype._cache = function () {
}

/*!
@function evt._cache.add(_el, _evt, fn)
@param 	_el: element to add eventhandler 
		_evt: type of eventhandler
		fn: function that should be called 
@abstract storing eventhandler (_type) calling function (_fn) on element (_el) into cache 
*/
evt.prototype._cache.add = function (_el, _evt, fn) {
			self._cachedEvts.push(arguments);
}

/*!
@function evt._cache.remove(_el, _evt, fn)
@param 	_el: element to add eventhandler 
		_evt: type of eventhandler
		fn: function that should be called 
@abstract removing eventhandler (_type) calling function (_fn) on element (_el) from cache 
*/
evt.prototype._cache.remove = function (_el,_evt,_fn) {
	var _n = _cachedEvts.length;
	while(_n--){ 
		if (self._cachedEvts[_n][0] === _el && self._cachedEvts[_n][1] === _evt && self._cachedEvts[_n][2] === _fn) {
			self._cachedEvts=self._cachedEvts.slice(0,_n).concat(self._cachedEvts.slice(_n+1,self._cachedEvts.length));
		}
	}
}

/*!
@function evt._cache.flush()
@abstract removing added eventhandlers, preventing memory leaks
*/
evt.prototype._cache.flush = function () {

	var _n = (self._cachedEvts.length);
	var item;
	while(_n--) {
		item = self._cachedEvts[_n];
		evt.remove(item[0],item[1],item[2],true);
	}
}


evt = new evt();

evt.add(window,'unload',evt._cache.flush);
