Return to Snippet

Revision: 12774
at May 17, 2009 13:22 by garside


Updated Code
/*!
 * jStack - jQuery Event Stack Management
 * by Eric Garside (http://eric.garside.name)
 * 
 * Dual licensed under:
 * 	MIT: http://www.opensource.org/licenses/mit-license.php
 *	GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
 */
(function($){
	
	$.extend($.fn, {
		// Determine the objects position in the cache, if any
		cachePosition: function(){
			return $.data(this[0]);
		},
		
		// Allow the user to splice an event into a specific position in the event cache 
		bindIntoStack: function(pos, type, func){
			return this.each(function(){
				var namespaces = type.split("."),	// Explode out namespaces, if any
					evType = namespaces.shift(),	// Grab the actual type
					el = $(this),					// Use the jQuery reference to the first element instead of the domElement
					position = el.cachePosition();	// Get the location of the element in the cache.
				
				if (!position) return;				// If we have a position, we can access the cache, which holds the jQuery event stack.
					
				var cache = $.cache[ position ];	// Grab a reference to the cache so we can do some sanity checks

				el.bind(type, func);				// Now we need to bind the new function to the call stack through jQuery

				if (!cache ||						// If we don't have the a pre-existing event cache, bind the function as a new entry and exit
					!cache.events || 
					!cache.events[ evType ]) return;	
					
				var events = cache.events[ evType ],// Grab a copy of the events cache for the given type
					fromExpando = [],				// [stackPosition => uuidIDInjQueryCache, ...]
					toReplace = null,				// A copy of the function we'll be replacing, if any
					i = 0;
					
				$.each(events, function(k){
					fromExpando.push(k);
					if (i == pos) toReplace = this;	// If the positions are equal, this is the function we want to replace
					++i;
				})
				
				if (!toReplace) return;		 		// If the position in the stack has not yet been reached, there's no slicing to be done

				var newPos = fromExpando.pop();		// The position we'll be placing in

				// Perform the actual position swap in the cache
				$.cache[ position ].events[ evType ][ fromExpando[pos] ] = $.cache[ position ].events[ evType ][ newPos ];
				$.cache[ position ].events[ evType ][ newPos ] = toReplace;
			})
			
			return this;
		}
	});
	
})(jQuery);

// Code to test with
$(function(){
	
	var test = $('#test')
		.bind('clickr.one', function(){ console.log('evt1') })
		.bind('clickr.two', function(){ console.log('evt2') })
		.bind('clickr.three', function(){ console.log('evt3') })
		.bind('clickr.four', function(){ console.log('evt4') })
		.bindIntoStack(0, 'clickr.override', function(e){
			console.log('I am now first, and I prevent all other events.');
			e.stopImmediatePropagation();
			return false;
		})
		.click(function(){ $(this).trigger('clickr') })
	$('#unbind').click(function(){ test.unbind('clickr.override') })
})

/**
 * Test HTML:
	<body>
		<button id="test">Test Events</button>
		<button id="unbind">Unbind Override Trigger</button>
	</body>
 */

Revision: 12773
at March 27, 2009 19:32 by garside


Initial Code
/*!
 * jStack - jQuery Event Stack Management
 * by Eric Garside (http://eric.garside.name)
 * 
 * Dual licensed under:
 * 	MIT: http://www.opensource.org/licenses/mit-license.php
 *	GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
 */
(function($){
	
	var rx = /^jQuery/;
	
	$.extend($.fn, {
		// Determine the objects position in the cache, if any
		cachePosition: function(){		
			var el = this[0],						// Get the reference to the first domElement
				position = null;					// The position of the element in the jQuery Cache, if any.
			
			$.each(el, function(k){					// Here comes risky business. Easiest way to get the cache position is to look for the jQuery Expando on the element. (ex: jQuery12381926469122).
				if (!rx.test(k)) return;			// If the attribute doesn't start with jQuery, move along.
				position = this*1;					// Otherwise, the object is in the cache, so store its cache position. (The value of the expando)
				return false;						// Then, break the loop.
			})
			
			return position;						// At this point, position will either be null or the objects position in the jQuery cache
		},
		
		// Allow the user to splice an event into a specific position in the event cache 
		bindIntoStack: function(pos, type, func){
			return this.each(function(){
				var namespaces = type.split("."),	// Explode out namespaces, if any
					evType = namespaces.shift(),	// Grab the actual type
					el = $(this),					// Use the jQuery reference to the first element instead of the domElement
					position = el.cachePosition();	// Get the location of the element in the cache.
				
				if (!position) return;				// If we have a position, we can access the cache, which holds the jQuery event stack.
					
				var cache = $.cache[ position ];	// Grab a reference to the cache so we can do some sanity checks

				el.bind(type, func);				// Now we need to bind the new function to the call stack through jQuery

				if (!cache ||						// If we don't have the a pre-existing event cache, bind the function as a new entry and exit
					!cache.events || 
					!cache.events[ evType ]) return;	
					
				var events = cache.events[ evType ],// Grab a copy of the events cache for the given type
					fromExpando = [],				// [stackPosition => uuidIDInjQueryCache, ...]
					toReplace = null,				// A copy of the function we'll be replacing, if any
					i = 0;
					
				$.each(events, function(k){
					fromExpando.push(k);
					if (i == pos) toReplace = this;	// If the positions are equal, this is the function we want to replace
					++i;
				})
				
				if (!toReplace) return;		 		// If the position in the stack has not yet been reached, there's no slicing to be done

				var newPos = fromExpando.pop();		// The position we'll be placing in

				// Perform the actual position swap in the cache
				$.cache[ position ].events[ evType ][ fromExpando[pos] ] = $.cache[ position ].events[ evType ][ newPos ];
				$.cache[ position ].events[ evType ][ newPos ] = toReplace;
			})
			
			return this;
		}
	});
	
})(jQuery);

// Code to test with
$(function(){
	
	var test = $('#test')
		.bind('clickr.one', function(){ console.log('evt1') })
		.bind('clickr.two', function(){ console.log('evt2') })
		.bind('clickr.three', function(){ console.log('evt3') })
		.bind('clickr.four', function(){ console.log('evt4') })
		.bindIntoStack(0, 'clickr.override', function(e){
			console.log('I am now first, and I prevent all other events.');
			e.stopImmediatePropagation();
			return false;
		})
		.click(function(){ $(this).trigger('clickr') })
	$('#unbind').click(function(){ test.unbind('clickr.override') })
})

/**
 * Test HTML:
	<body>
		<button id="test">Test Events</button>
		<button id="unbind">Unbind Override Trigger</button>
	</body>
 */

Initial URL


Initial Description
Allows the user to bind an event into a certain position in the call stack for events.

Initial Title
jStack - jQuery Event Stack Management

Initial Tags
jquery, order

Initial Language
JavaScript