      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