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