├── README.md ├── jquery.inputevent.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # jQuery plugin to provide a cross browser oninput event 2 | 3 | 4 | 5 | this is fork of http://whattheheadsaid.com/projects/input-special-event 6 | 7 | 8 | it fixes some bugs duo changed jquery api. 9 | -------------------------------------------------------------------------------- /jquery.inputevent.js: -------------------------------------------------------------------------------- 1 | /* 2 | jQuery `input` special event v1.2 3 | http://whattheheadsaid.com/projects/input-special-event 4 | 5 | (c) 2010-2011 Andy Earnshaw 6 | forked by dodo (https://github.com/dodo) 7 | MIT license 8 | www.opensource.org/licenses/mit-license.php 9 | */ 10 | (function($, udf) { 11 | var ns = ".inputEvent ", 12 | // A bunch of data strings that we use regularly 13 | dataBnd = "bound.inputEvent", 14 | dataVal = "value.inputEvent", 15 | dataDlg = "delegated.inputEvent", 16 | // Set up our list of events 17 | bindTo = [ 18 | "input", "textInput", 19 | "propertychange", 20 | "paste", "cut", 21 | "keydown", "keyup", 22 | "drop", 23 | ""].join(ns), 24 | // Events required for delegate, mostly for IE support 25 | dlgtTo = [ "focusin", "mouseover", "dragstart", "" ].join(ns) + bindTo, 26 | // Elements supporting text input, not including contentEditable 27 | supported = {TEXTAREA:udf, INPUT:udf}, 28 | // Events that fire before input value is updated 29 | delay = { paste:udf, cut:udf, keydown:udf, drop:udf, textInput:udf }; 30 | 31 | // this checks if the tag is supported or has the contentEditable property 32 | function isSupported(elem) { 33 | return $(elem).prop('contenteditable') == "true" || 34 | elem.tagName in supported; 35 | }; 36 | 37 | $.event.special.txtinput = { 38 | setup: function(data, namespaces, handler, onChangeOnly) { 39 | var timer, 40 | bndCount, 41 | // Get references to the element 42 | elem = this, 43 | $elem = $(this), 44 | triggered = false; 45 | 46 | if (isSupported(elem)) { 47 | bndCount = $.data(elem, dataBnd) || 0; 48 | 49 | if (!bndCount) 50 | $elem.bind(bindTo, handler); 51 | 52 | $.data(elem, dataBnd, ++bndCount); 53 | $.data(elem, dataVal, elem.value); 54 | } else { 55 | $elem.bind(dlgtTo, function (e) { 56 | var target = e.target; 57 | if (isSupported(target) && !$.data(elem, dataDlg)) { 58 | bndCount = $.data(target, dataBnd) || 0; 59 | 60 | if (!bndCount) { 61 | $(target).bind(bindTo, handler); 62 | handler.apply(this, arguments); 63 | } 64 | 65 | // make sure we increase the count only once for each bound ancestor 66 | $.data(elem, dataDlg, true); 67 | $.data(target, dataBnd, ++bndCount); 68 | $.data(target, dataVal, target.value); 69 | } 70 | }); 71 | } 72 | function handler (e) { 73 | var elem = e.target; 74 | 75 | // Clear previous timers because we only need to know about 1 change 76 | window.clearTimeout(timer), timer = null; 77 | 78 | // Return if we've already triggered the event 79 | if (triggered) 80 | return; 81 | 82 | // paste, cut, keydown and drop all fire before the value is updated 83 | if (e.type in delay && !timer) { 84 | // ...so we need to delay them until after the event has fired 85 | timer = window.setTimeout(function () { 86 | if (elem.value !== $.data(elem, dataVal)) { 87 | $(elem).trigger("txtinput"); 88 | $.data(elem, dataVal, elem.value); 89 | } 90 | }, 0); 91 | } 92 | else if (e.type == "propertychange") { 93 | if (e.originalEvent.propertyName == "value") { 94 | $(elem).trigger("txtinput"); 95 | $.data(elem, dataVal, elem.value); 96 | triggered = true; 97 | window.setTimeout(function () { 98 | triggered = false; 99 | }, 0); 100 | } 101 | } 102 | else { 103 | var change = onChangeOnly !== undefined ? onChangeOnly : 104 | $.fn.input.settings.onChangeOnly; 105 | if ($.data(elem, dataVal) == elem.value && change) 106 | return; 107 | 108 | $(elem).trigger("txtinput"); 109 | $.data(elem, dataVal, elem.value); 110 | triggered = true; 111 | window.setTimeout(function () { 112 | triggered = false; 113 | }, 0); 114 | } 115 | } 116 | }, 117 | teardown: function () { 118 | var elem = $(this); 119 | elem.unbind(dlgtTo); 120 | elem.find("input, textarea").andSelf().each(function () { 121 | bndCount = $.data(this, dataBnd, ($.data(this, dataBnd) || 1)-1); 122 | 123 | if (!bndCount) 124 | elem.unbind(bindTo); 125 | }); 126 | } 127 | }; 128 | 129 | // Setup our jQuery shorthand method 130 | $.fn.input = function (handler) { 131 | return handler ? $(this).bind("txtinput", handler) : this.trigger("txtinput"); 132 | } 133 | 134 | $.fn.input.settings = { 135 | onChangeOnly: false 136 | }; 137 | 138 | })(jQuery); 139 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { "name": "jquery-inputevent" 2 | , "description": "Cross browser oninput event for jQuery" 3 | , "version": "0.2.0" 4 | , "homepage": "https://github.com/dodo/jquery-inputevent" 5 | , "author": "Andy Earnshaw (http://whattheheadsaid.com/)" 6 | , "contributors": [ 7 | "dodo (https://github.com/dodo)" 8 | , "Eduardo Kozachek " 9 | ] 10 | , "main": "jquery.inputevent.js" 11 | , "repository": {"type": "git", "url": "git://github.com/dodo/jquery-inputevent.git"} 12 | , "engines": {"browser": ""} 13 | } 14 | --------------------------------------------------------------------------------