/**
 * jQuery alternative bind plug-in 1.0.0
 * @author yzhu
 * this plug-in has exactly same signatures as the jQuery.bind and similar functionality. The only difference is that
 * bindOnTop will bind the handler to event on top of the stack of handlers, which means this handler will be executed first
 * when the event is fired.
 * implementation: 
 * 1. retrieve the existing handlers list for each matched element;
 * 2. make the clone of the list
 * 3. unbind all the handlers for the matched element
 * 4. bind the new handler (so it is on top of the stack)
 * 5. rebind the existing handlers (so all existing handers are behind the new handler)
 * 
 * mergeBind wraps all handlers into a wrapper function, and still keeps the order they registered.
 * this solution aims to multiple handlers binding to "submit" event while the second hanlder seems not 
 * to be executed properly sometimes.
 */
(function($){
	$.fn.bindOnTop = function(type,data,fn) { 
		this.each(function(){
			//retrieve the existing handlers list for each matched element;
			var handlers = ( jQuery.data(this, "events") || {} )[type];
			//make the clone of the list
			var handlersClone = clone(handlers);
			//unbind all the handlers for the matched element
			jQuery.event.remove( this, type );
			//bind the new handler (so it is on top of the stack)
			jQuery.event.add( this, type, fn || data, fn && data );
			//rebind the existing handlers
			for ( var j in handlersClone ) {
				var handler = handlersClone[j];
				jQuery.event.add( this, type, handler );
			}
		});
	};
	$.fn.mergeBind = function(type,data,fn) { 
		this.bind(type,data,fn);
		this.each(function(){
			var handlers = ( jQuery.data(this, "events") || {} )[type];
			var handlersClone = clone(handlers);
			jQuery.event.remove( this, type ); //remove all existing event handlers
			//create a wrapper function
			var wrapper = function(){
				for ( var j in handlersClone ) {
					var handler = handlersClone[j];
					//if any of handlers explicitly returns false,
					//the wrapper will return false immediately and all rest handlers won't be executed.
					if (handler.apply(this)==false) return false;
				}
			};
			//bind the wrapper function as event handler, no more multiple handlers
			jQuery.event.add( this, type, wrapper );
		});
	} 
})(jQuery);


function clone(obj){
    if(obj == null || typeof(obj) != 'object')
        return obj;
    var temp = new obj.constructor(); // changed (twice)
    for(var key in obj)
        temp[key] = clone(obj[key]);
    return temp;
}


