1 /**
  2  * http://plugins.jquery.com/project/focus
  3  * JQUERY FOCUS 1.0.0
  4  * Submitted by erikkallen on November 9, 2009 - 5:31pm
  5  * http://plugins.jquery.com/node/11272/release
  6  **/
  7 (function($) {
  8 
  9 function sameOrChild(n1, n2) {
 10 	// http://www.quirksmode.org/blog/archives/2006/01/contains_for_mo.html
 11 	return n1 === n2 || (typeof(n1.contains) !== 'undefined' ? n1.contains(n2) : !!(n1.compareDocumentPosition(n2) & 16));
 12 }
 13 
 14 function focusHandler(event) {
 15 	event = $.event.fix(event || window.event), $this = $(this), isFocused = $this.data('focus.isFocused');
 16 	if (!isFocused) {
 17 		$this.data('focus.isFocused', true);
 18 		event.type = 'focusin';
 19 		return $.event.handle.apply(this, [event]);
 20 	}	
 21 }
 22 
 23 function blurHandler(event) {
 24 	var args = [].slice.call(arguments, 1), $this = $(this);
 25 	event = $.event.fix(event || window.event);
 26 
 27 	window.setTimeout(function() {
 28 		if (!sameOrChild($this.get(0), document.activeElement)) {
 29 			$this.data('focus.isFocused', false);
 30 			event.type = 'focusout';
 31 			return $.event.handle.apply($this.get(0), [event]);
 32 		}
 33 	}, 0);
 34 }
 35 
 36 function setupEvents(elem) {
 37 	var $elem = $(elem), ref = $elem.data('focus.handlerReferences') || 0;
 38 	if (ref == 0) {
 39 		if (elem.addEventListener) {
 40 			elem.addEventListener('focus', focusHandler, true);
 41 			elem.addEventListener('blur', blurHandler, true);
 42 		}
 43 		else {
 44 			elem.onfocusin  = focusHandler;
 45 			elem.onfocusout = blurHandler;
 46 		}
 47 	}
 48 	$elem.data('focus.handlerReferences', ref + 1)
 49 	$elem.data('focus.isFocused', sameOrChild(elem, document.activeElement));
 50 }
 51 
 52 function teardownEvents(elem) {
 53 	var $elem = $(elem), ref = $elem.data('focus.handlerReferences') || 0;
 54 	if (ref == 1) {
 55 		if (elem.removeEventListener) {
 56 			elem.removeEventListener('focus', focusHandler, true);
 57 			elem.removeEventListener('blur', blurHandler, true);
 58 		}
 59 		else {
 60 			elem.onfocusin  = null;
 61 			elem.onfocusout = null;
 62 		}
 63 		$elem.removeData('focus.handlerReferences')
 64 		$elem.removeData('focus.isFocused');
 65 	}
 66 	else {
 67 		$elem.data('focus.handlerReferences', ref - 1);
 68 	}
 69 }
 70 
 71 $.each(['focusin', 'focusout'], function(i, x) {
 72 	$.event.special[x] = {
 73 		setup: function() { setupEvents(this); },
 74 		teardown: function() { teardownEvents(this); }
 75 	};
 76 });
 77 
 78 $.fn.extend({
 79 	focusin: function(fn) {
 80 		return fn ? this.bind('focusin', fn) : this.trigger('focusin');
 81 	},
 82 	focusout: function(fn) {
 83 		return fn ? this.bind('focusout', fn) : this.trigger('focusout');
 84 	}
 85 });
 86 
 87 })(jQuery);
 88