You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
4.5 KiB
118 lines
4.5 KiB
/*
|
|
jQuery `input` special event v1.1
|
|
|
|
<a class="linkclass" href="http://whattheheadsaid.com/projects/input-special-event">http://whattheheadsaid.com/projects/input-special-event</a>
|
|
|
|
(c) 2010-2011 Andy Earnshaw
|
|
MIT license
|
|
<a class="linkclass" href="http://www.opensource.org/licenses/mit-license.php">www.opensource.org/licenses/mit-license.php</a>
|
|
*/
|
|
(function($, udf) {
|
|
var ns = ".inputEvent ",
|
|
// A bunch of data strings that we use regularly
|
|
dataBnd = "bound.inputEvent",
|
|
dataVal = "value.inputEvent",
|
|
dataDlg = "delegated.inputEvent",
|
|
txtinput = "txtinput",
|
|
// Set up our list of events
|
|
bindTo = [
|
|
"input", "textInput", "propertychange", "paste", "cut", "keydown", "drop",
|
|
""].join(ns),
|
|
// Events required for delegate, mostly for IE support
|
|
dlgtTo = [ "focusin", "mouseover", "dragstart", "" ].join(ns),
|
|
// Elements supporting text input, not including contentEditable
|
|
supported = {TEXTAREA:udf, INPUT:udf},
|
|
// Events that fire before input value is updated
|
|
delay = { paste:udf, cut:udf, keydown:udf, drop:udf, textInput:udf };
|
|
|
|
$.event.special.txtinput = {
|
|
setup: function(data, namespaces, handler) {
|
|
var timer,
|
|
bndCount,
|
|
// Get references to the element
|
|
elem = this,
|
|
$elem = $(this),
|
|
triggered = false;
|
|
|
|
if (elem.tagName in supported) {
|
|
bndCount = $.data(elem, dataBnd) || 0;
|
|
|
|
if (!bndCount)
|
|
$elem.bind(bindTo, handler);
|
|
|
|
$.data(elem, dataBnd, ++bndCount);
|
|
$.data(elem, dataVal, elem.value);
|
|
} else {
|
|
$elem.bind(dlgtTo, function (e) {
|
|
var target = e.target;
|
|
if (target.tagName in supported && !$.data(elem, dataDlg)) {
|
|
bndCount = $.data(target, dataBnd) || 0;
|
|
|
|
if (!bndCount)
|
|
target.bind(bindTo, handler);
|
|
|
|
// make sure we increase the count only once for each bound ancestor
|
|
$.data(elem, dataDlg, true);
|
|
$.data(target, dataBnd, ++bndCount);
|
|
$.data(target, dataVal, target.value);
|
|
}
|
|
});
|
|
}
|
|
function handler (e) {
|
|
var elem = e.target;
|
|
|
|
// Clear previous timers because we only need to know about 1 change
|
|
window.clearTimeout(timer), timer = null;
|
|
|
|
// Return if we've already triggered the event
|
|
if (triggered)
|
|
return;
|
|
|
|
// paste, cut, keydown and drop all fire before the value is updated
|
|
if (e.type in delay && !timer) {
|
|
// ...so we need to delay them until after the event has fired
|
|
timer = window.setTimeout(function () {
|
|
if (elem.value !== $.data(elem, dataVal)) {
|
|
$(elem).trigger(txtinput);
|
|
$.data(elem, dataVal, elem.value);
|
|
}
|
|
}, 0);
|
|
}
|
|
else if (e.type == "propertychange") {
|
|
if (e.originalEvent.propertyName == "value") {
|
|
$(elem).trigger(txtinput);
|
|
$.data(elem, dataVal, elem.value);
|
|
triggered = true;
|
|
window.setTimeout(function () {
|
|
triggered = false;
|
|
}, 0);
|
|
}
|
|
}
|
|
else {
|
|
$(elem).trigger(txtinput);
|
|
$.data(elem, dataVal, elem.value);
|
|
triggered = true;
|
|
window.setTimeout(function () {
|
|
triggered = false;
|
|
}, 0);
|
|
}
|
|
}
|
|
},
|
|
teardown: function () {
|
|
var elem = $(this);
|
|
elem.unbind(dlgtTo);
|
|
elem.find("input, textarea").andSelf().each(function () {
|
|
bndCount = $.data(this, dataBnd, ($.data(this, dataBnd) || 1)-1);
|
|
|
|
if (!bndCount)
|
|
elem.unbind(bindTo);
|
|
});
|
|
}
|
|
};
|
|
|
|
// Setup our jQuery shorthand method
|
|
$.fn.input = function (handler) {
|
|
return handler ? this.bind(txtinput, handler) : this.trigger(txtinput);
|
|
}
|
|
})(jQuery);
|