// JavaScript Document// JavaScript Document
/*


---------------------------------------------------------------
Notes
---------------------------------------------------------------
Currently MOUSEOUT DOESN'T WORK properly with firefox and should therefore be avoided for critical event
Any function returning false triggers event.stopPropagation and event.preventDefault (or IE equivalent);

The submit event is not correctly handled by internet explorer and is therefore replaced by a livequery on IE

Events object passed have only two attributes : type, target. They might have more, but these two attributes are the only two that are always passed
*/

(function( $ )
{
	/** delegate method
	*
	* @param expr f    a filter that will be applied to the target element using the is keyword. filters should evaluate quickly as there might be a lot of filter applied to a given event type.
	* @param eventtype m     an event type (click, mouseover, mouseup, focus, blur,... ) all event type are decently supported appart from mouseout which doesn't bubble properly
	* @param function c     a function that is run when the target element is filtered. The this keyword is the target element, and the event is passed as the first argument. If the function returns false, the stopPropagation and preventDefault Methods are applied.
	*/
	$.delegate = function( f, m, c )
	{
		try
		{
		if (c == null){
			//console.log(m);
			$.delegateMethods.removeEvent(f , m);
		} else {
			$.delegateMethods.addEvent( m, f, c);
		}
		}
		catch(e)
		{
			if(console != undefined) console.log(e);
		}
	};

	$.delegateMethods = {
	triggers: {},
	events: {},
	addEvent : function (type, filter, action){
		if (!$.delegateMethods.events[type]){
			$.delegateMethods.events[type] = [];
		}


		if( type =='submit')
		{
			$(filter).livequery(type,action);
			return;
		}

		if( !$.delegateMethods.triggers[type] ){


			$.delegateMethods.triggers[type] = type;

			if(type == 'focus'){
				$.delegateMethods.patchEvent('focus', function(target){$.delegateMethods.check(target)}, true);
			} else if(type == 'blur'){
				$.delegateMethods.patchEvent('blur', function(target){$.delegateMethods.check(target)}, true);
			}else if(type == 'submit'){
				$.delegateMethods.patchEvent('submit', function(target){$.delegateMethods.check(target)}, true);
			}else {
				$(document).bind(type, function(target){
					$.delegateMethods.check(target );
				});
			}
		}


		pos = $.delegateMethods.getPos(filter, type);
		if (pos == -1){
			$.delegateMethods.events[type].push({ 'filter': filter, 'action': action });
		} else {
			$.delegateMethods.events[type][pos].filter = filter;
			$.delegateMethods.events[type][pos].action = action;
		}
	},

	getPos : function( filter, type){
		var todo = $.delegateMethods.events[type];
		var it = todo.length -1 || 0;
		try{
		do{
			if (todo[it].filter == filter){
				return it;
			}
		}while(it--);
		}catch(e){};

		return -1;
	},
	removeEvent : function( filter, type ){

		if (type != null){
			var todo = $.delegateMethods.events[type];
			if(todo){
				var it = todo.length -1 || 0;

				try{
				do{
					if (todo[it].filter == filter){
						delete($.delegateMethods.events[type][it]);
					}
				}while(it--);
				}catch(e){};
			}
		} else {
			var it = $.delegateMethods.triggers.length;

			do{
				if($.delegateMethods.events[$.delegateMethods.triggers[it-1]]){
					var it2 = $.delegateMethods.events[$.delegateMethods.triggers[it-1]].length -1 || 0;
					try{
					do{
						if ($.delegateMethods.events[$.delegateMethods.triggers[it-1]][it2].filter == filter){
							delete($.delegateMethods.events[$.delegateMethods.triggers[it-1]][it2]);
						}
					}while(it2--);
					}catch(e){};
				}

			}while(it--);

		}
	},
	check : function(e){
		var oldE = e.target;
		var targetDom = $.delegateMethods.buildUp(e.target),
		target = e.target;

		if (!targetDom){
			return;
		}


		var todo = $.delegateMethods.events[e.type];
		if (!todo){
			return;
		}

		var it = (todo.length ) || 0;


		if (it){
			it--;
			do{
				try{

					$(todo[it].filter, targetDom).each(function(){

						var cpt = this.nodeIt
							while(cpt--){
								e.target= e.target.parentNode;
							};


						$.delegateMethods.applyEvent(e, todo[it].action);
					});


				} catch (e) {
				}
			}while(it--);
		}
	},

	attach: function(){
	},

	//(t)ype of event, (h)andler function, (b)ubbles boolean
	patchEvent: function( t, h, b ){
		if (document.addEventListener){
			document.addEventListener(t,
					function(target){
						target_ = {'type': target.type, 'target': target.target, 'currentTarget': target.currentTarget, 'eventPhase': target.eventPhase}


						$.delegateMethods.applyEvent(target_, h);
					}
			, b);
		} else {
			switch(t){
				case 'focus' : t2='onactivate'; break;
				case 'blur' : t2='ondeactivate'; break;
				default : t2=t;
			}
			document.attachEvent(t2, function(target){
				//renames the event type
				_target = {'type': t, 'target': target.srcElement};

				$.delegateMethods.applyEvent(_target, h);
			 });

		}
	},
	applyEvent: function( target, h ){
		$.delegateMethods.upgrade(target);
		res = h.apply(target.target, [target]);
		if (res == false ){
			target.preventDefault();
			target.stopPropagation();
		}

	},
	upgrade : function( e ){
		if (e.preventDefault == null){
			e.preventDefault = function(){
				this.returnValue = false;
			}
		}
		if (e.stopPropagation == null){
			e.stopPropagation = function(){
				window.event.cancelBubble = true;
			}
		}
	}, buildUp : function(elem){



		e = elem;
		var childClone = null;
			var nodeIt =0;
			cloneE = null;
			while ( e != document && e != undefined ){
				cloneE = e.cloneNode(false);

					if (childClone){
						cloneE.appendChild(childClone);
					} else {

						//this part breaks with IE but is not essential so we just coment it out for the moment

						/*i = 0;
						var length = e.childNodes.length;

						while (i < length){
							var clone = e.childNodes[i].cloneNode(false);
							if (clone && cloneE.appendChild){
								try{
									cloneE.appendChild(clone);
								} catch (e){
								}
							}
							i++;
						};*/

					}

					//at this point we have a an exactClone of the current Node
					cloneE.nodeIt = nodeIt;
					childClone = cloneE;

					e = e.parentNode;

					nodeIt++;


			}


			return cloneE;

	}

}



})( jQuery );





/*$(function(){
	//var triggers = ['click', 'focus', 'keydown'];
	//['click', 'blur', 'change', 'dblclick', 'error', 'focus', 'keydown', 'keypress', 'keyup', 'mousedown', 'mouseout', 'mouseover', 'submit', 'select'];
	for (var it in $.delegateMethods.triggers){
		$('body').bind($.delegateMethods.triggers[it], function(target){
			$.delegateMethods.check(target );
		});

	}

});*/
