jQuery Plugin: Event Filter

December 14, 2009 | Download

Event's are a large part of what makes jQuery so powerful. A lesser known piece of information is that all event's binded through jQuery, are actually stored in the 'events' portion of that elements data object.

jQuery(function($){
	var $events = $('.event-filter-example');
	// Bind some events to the example
	$events.filter(':odd').click(function(){
		alert('This is an example click event');
	})
	$events.filter(':even').bind('mouseover.event-namespace', function(){
		$(this).css('color', 'purple');
	})
	$events.eq(0).bind('mouseover.event-new-namespace', function(){
		$(this).css('color', 'yellow');
	})
	$events.eq(1).bind('mouseout', function(){
		$(this).css('color', 'black');
	})
	$events.eq(2).bind('myevent.namespace', function(){
		alert('This is the ' + event.type + ' event');
	});

	// Log info into firebug if present
	if (console){
		console.group( 'Events of Filter Example: - ');
		console.log( 'First DIV - ', $events.eq(0).data('events') );
		console.log( 'Second DIV - ', $events.eq(1).data('events') );
		console.log( 'Third DIV - ', $events.eq(2).data('events') );
		console.groupEnd( 'Events of Filter Example: - ');
	}
});

This is an the example div
This is an the example div
This is an the example div


If you open up firebug, you will see a grouping with the 'Events of Filter Example' as the title. The group contains all events attached to each div, including the custom event's.

The Event Filter

The Event filter gives the ability to filter out a set of elements that only contain (or don't contain) the event specified. Here is an example with the above set of DIV's.

jQuery(function($){
	// Console only function
	if (!console) return;

	// Cache events
	var $events = $('.event-filter-example');

	// Log info into firebug
	console.group('Using the Event Filter');

	console.log( $events.filter(':Event(click)'), "Elements with 'click' event" );
	console.log( $events.filter(':Event(!click)'), "Elements with NO 'click' event" );
	console.log( $events.filter(':Event(mouseout)'), "Elements with 'mouseout' events" );
	console.log( $events.filter(':Event(mouseover.event-new-namespace)'), "Elements with 'mouseover.event-new-namespace' events" );
	console.log( $events.filter(':Event(myevent)'), "Elements with 'myevent' events" );
	console.log( $events.filter(':Event(.event-namespace)'), "Elements with '.event-namespace' event" );

	console.groupEnd('Using the Event Filter');
});

As shown above, the Event filter supports namespace searches along with searching for elements without the event with the 'not' operator. For events that contain the '!' at the start of their name, simply escape out the operator. Remember though, double slashes are required since javascript renders a single slash as an escaper, and won't pass it on to the filter function.

Note*: The reason the 'Event' filter is capitalized is so the :even filter doesn't overwrite it. jQuery uses regex on it's filters, and the even filter takes precedence over custom filter's.

The source code is provided below, along with a zip file containing a small example page of usage.

/*!
 * jQuery Event Filter
 * December 13, 2009
 * Corey Hart @ http://www.codenothing.com
 */ 
(function($, undefined){
	// Initialize vars together
	var original, notOperator = false, name, namespace, events, firstChar, i, k;

	// Event filter needs to be capitalized so it doesn't clash with 'even' filter
	$.expr[':'].Event = function(elem, index, params, group){
		// Return false if element doesn't exist, or no query string wasn't provided
                if (elem === undefined || ! params[3] || params[3] == '')
                        return false;
                // Run parsing if new query
                else if (original !== params[3]){
			// Will replace original var later
			original = params[3].split('.');
			// First is the name of the event
			name = original.shift();
			// Add ability to filter by elements that don't have the event
			notOperator = ((firstChar = name.substr(0,1)) === '!');
			// If not operator exists or user is escaping it out as it's part of the event name,
			// remove the name's first character
			if (notOperator || firstChar === "\\") name = name.substr(1);
			// Sort the namespace's like jQuery does in the event module
			namespace = original.sort().join('.');
			// Restore the original param for less processing
			original = params[3];
		}

		// Ensure events exist on element
		if (! (events = $(elem).data('events')) )
			return notOperator;
		// Run check for when only the namespace is passed
		// (Slower, especially when lots of events are attached)
		else if (! name && namespace.length){
			// Search for purely namespaced based event
			for (i in events)
				if (events[i])
					for (k in events[i])
						if (events[i][k].type && events[i][k].type === namespace)
							return !notOperator;
			// Event namespace not found
			return notOperator;
		}
		// Check to ensure event exists on the event object
		else if ( !events[name] )
			return notOperator;
		// Name && namespace passed
		else if ( namespace.length ){
			// Search for namespaced event
			for (i in events[name])
				if (events[name][i].type && events[name][i].type == namespace)
					return !notOperator;
			// Event not found
			return notOperator;
		}

		// No namespace was was defined, so only the event was desired
		return !notOperator;
	};
})(jQuery);

Download

Latest: event-filter.zip
Released: December 14, 2009
-Initial Release
Have a question or comment? ask@codenothing.com.