/** * Copyright (c) 2008, Ben XO * * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * * This is a jQuery plugin that allows events to be handled in reverse order of * binding - add events to the head of the queue rather than the end. * * Particularly useful if you apply your "do"s in a modular order and wish to * apply your "undo"s in reverse order. * * It adds the following two methods: * * reverse(event): reverses the order that functions attached to are * applied to this element. * * stack( event, data, fn ): just like bind(), except adds to the front of the * event queue instead of the end. * * Also, every event method (.click(), .focus(), .resize(), .submit(), etc - * 21 methods in all) can take an extra parameter "reverse" that controls if * the event is added to the front or end of the event queue. For example: * * $("body").click(function() { alert("1"); }); * $("body").click(function() { alert("2"); }); * $("body").click(function() { alert("3"); }, true); * * ... will show "3", "1" then "2" when the document is clicked. * * @version 0.3 */ jQuery.fn.extend({ // reverse the order of events bound to an element reverse: function( event ) { var events = this.data("events"); if ( events != undefined && events[event] != undefined) { // can't reverse what's not there var reverseEvent = new Array; for (var e in events[event]) { reverseEvent.unshift(events[event][e]); } events[event] = reverseEvent; } return this; }, // add an event to the front of an event queue rather than the back // we do this by reversing the queue, adding, then reversing again stack: function( event, data, fn ) { return this .reverse( event ) .bind( event, data, fn ) .reverse( event ) ; }, hover: function( fnOver, fnOut, reverse ) { if(reverse) { return this .stack('mouseenter', fnOver) .stack('mouseleave', fnOut) ; } else { return this .bind('mouseenter', fnOver) .bind('mouseleave', fnOut) ; } } }); // every event handler - blur(), focus(), click() etc now has a 2nd param which // if true will add the passed function to the beginning of the event list // instead of the end jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," + "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + "submit,keydown,keypress,keyup,error").split(","), function(i, name){ // Handle event binding jQuery.fn[name] = function(fn, reverse){ if(fn) { return reverse ? this.stack(name, fn) : this.bind(name, fn) ; } else { return this.trigger(name); } }; });