Created
October 25, 2011 19:27
-
-
Save midu/1313941 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($){ | |
var current, | |
rnamespaces = /\.(.*)$/, | |
returnFalse = function(){return false}, | |
returnTrue = function(){return true}; | |
/** | |
* @function | |
* @parent jquery.event.pause | |
* Pauses an event (to be resumed later); | |
*/ | |
// | |
/** | |
* @function | |
* @parent jquery.event.pause | |
* | |
* Resumes an event | |
*/ | |
// | |
/** | |
* @page jquery.event.pause Pause-Resume | |
* @plugin jquery/event/pause | |
* @parent specialevents | |
* The jquery/event/pause plugin adds the ability to pause and | |
* resume events. | |
* | |
* $('#todos').bind('show', function(ev){ | |
* ev.pause(); | |
* | |
* $(this).load('todos.html', function(){ | |
* ev.resume(); | |
* }); | |
* }) | |
* | |
* When an event is paused, stops calling other event handlers for the | |
* event (similar to event.stopImmediatePropagation() ). But when | |
* resume is called on the event, it will begin calling events on event handlers | |
* after the 'paused' event handler. | |
* | |
* | |
* Pause-able events complement the [jQuery.event.special.default default] | |
* events plugin, providing the ability to easy create widgets with | |
* an asynchronous API. | |
* | |
* ## Example | |
* | |
* Consider a basic tabs widget that: | |
* | |
* - trigger's a __show__ event on panels when they are to be displayed | |
* - shows the panel after the show event. | |
* | |
* The sudo code for this controller might look like: | |
* | |
* $.Controller('Tabs',{ | |
* ".button click" : function( el ){ | |
* var panel = this.getPanelFromButton( el ); | |
* panel.triggerAsync('show', function(){ | |
* panel.show(); | |
* }) | |
* } | |
* }) | |
* | |
* Someone using this plugin would be able to delay the panel showing until ready: | |
* | |
* $('#todos').bind('show', function(ev){ | |
* ev.pause(); | |
* | |
* $(this).load('todos.html', function(){ | |
* ev.resume(); | |
* }); | |
* }) | |
* | |
* Or prevent the panel from showing at all: | |
* | |
* $('#todos').bind('show', function(ev){ | |
* if(! isReady()){ | |
* ev.preventDefault(); | |
* } | |
* }) | |
* | |
* ## Limitations | |
* | |
* The element and event handler that the <code>pause</code> is within can not be removed before | |
* resume is called. | |
* | |
* ## Big Example | |
* | |
* The following example shows a tabs widget where the user is prompted to save, ignore, or keep editing | |
* a tab when a new tab is clicked. | |
* | |
* @demo jquery/event/pause/pause.html | |
* | |
* It's a long, but great example of how to do some pretty complex state management with JavaScriptMVC. | |
* | |
*/ | |
$.Event.prototype.isPaused = returnFalse | |
$.Event.prototype.pause = function(){ | |
current = this; | |
this.stopImmediatePropagation(); | |
this.isPaused = returnTrue; | |
}; | |
$.Event.prototype.resume = function(){ | |
this.isPaused = this.isImmediatePropagationStopped = this.isPropagationStopped = returnFalse; | |
var el = this.liveFired || this.currentTarget || this.target, | |
defult = $.event.special['default'], | |
oldType = this.type; | |
// if we were in a 'live' -> run our liveHandler | |
if(this.handleObj.origHandler){ | |
var cur = this.currentTarget; | |
this.currentTarget = this.liveFired; | |
this.liveFired = undefined; | |
liveHandler.call(el, this, cur ); | |
el = cur; | |
} | |
if(this.isImmediatePropagationStopped()){ | |
return false; | |
} | |
// skip the event the first pass because we've already handled it | |
this.firstPass = true; | |
if(!this.isPropagationStopped()){ | |
$.event.trigger(this, [this.handleObj], el, false); | |
} | |
}; | |
function liveHandler( event, after ) { | |
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, | |
elems = [], | |
selectors = [], | |
events = jQuery._data( this, "events" ); | |
// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) | |
if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { | |
return; | |
} | |
if ( event.namespace ) { | |
namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); | |
} | |
event.liveFired = this; | |
var live = events.live.slice(0); | |
for ( j = 0; j < live.length; j++ ) { | |
handleObj = live[j]; | |
if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { | |
selectors.push( handleObj.selector ); | |
} else { | |
live.splice( j--, 1 ); | |
} | |
} | |
match = jQuery( event.target ).closest( selectors, event.currentTarget ); | |
for ( i = 0, l = match.length; i < l; i++ ) { | |
close = match[i]; | |
for ( j = 0; j < live.length; j++ ) { | |
handleObj = live[j]; | |
if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { | |
elem = close.elem; | |
related = null; | |
// Those two events require additional checking | |
if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { | |
event.type = handleObj.preType; | |
related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; | |
// Make sure not to accidentally match a child element with the same selector | |
if ( related && jQuery.contains( elem, related ) ) { | |
related = elem; | |
} | |
} | |
if ( !related || related !== elem ) { | |
elems.push({ elem: elem, handleObj: handleObj, level: close.level }); | |
} | |
} | |
} | |
} | |
for ( i = 0, l = elems.length; i < l; i++ ) { | |
match = elems[i]; | |
// inserted to only call elements after this point ... | |
if(after) { | |
if(after === match.elem){ | |
after = undefined; | |
} | |
continue; | |
} | |
if ( maxLevel && match.level > maxLevel ) { | |
break; | |
} | |
event.currentTarget = match.elem; | |
event.data = match.handleObj.data; | |
event.handleObj = match.handleObj; | |
ret = match.handleObj.origHandler.apply( match.elem, arguments ); | |
if ( ret === false || event.isPropagationStopped() ) { | |
maxLevel = match.level; | |
if ( ret === false ) { | |
stop = false; | |
} | |
if ( event.isImmediatePropagationStopped() ) { | |
break; | |
} | |
} | |
} | |
return stop; | |
} | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment