2
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.com/yui/license.html
8
YUI.add('value-change', function(Y) {
12
* <p>Event that fires when a text or input field has changed value as a result of a keystroke.
13
* Attaches a timed-out listener on the keydown event, and keeps the value to provide support
14
* for multi-keystroke character sets.</p>
15
* <p>This event fires when the value of the element changes, either as a result of
16
* a keystroke, or an IME input event.</p>
17
* <p>This does not replace the DOM onchange event, but rather augments it to do onchange-like
18
* logic as a result of key presses, even in multi-stroke character sets.</p>
20
* <p>Known issue: If attaching to elements that are not yet available, then only the first
21
* node will be guaranteed to have the event handler attached.</p>
25
* @param type {String} 'valueChange'
26
* @param fn {Function} the callback function
27
* @param el {String|Node|etc} the element(s) to bind
28
* @param o {Object} optional context object
29
* @param args 0..n additional arguments that should be provided
31
* @return {Event.Handle} the detach handle
34
function toNodeList (el) { return (
35
(Y.Lang.isString(el) || Y.Lang.isArray(el))
37
: (el instanceof Y.Node)
39
: (el instanceof Y.NodeList)
44
function onAvail (el, args) {
45
var h = Y.on("available", function () {
46
h.handle = Y.on.apply(Y, args);
51
function attachProxy (node, args) {
52
// args = [type, fn, el, o, ...]
53
// node.on(type, fn, o, ...);
54
args[0] = ceName(node);
57
// if event-custom is loaded, then this is gonna do something.
58
// otherwise, it's basically just a no-op.
59
node.publish(args[0], {
64
var registry = attachTriggers(node),
65
proxyHandle = node.on.apply(node, args);
70
function ceName (node) {
71
return Y.stamp(node) + "-" + eventName;
74
function attachDomEventHandlers (handlers, node) {
76
for (var i in handlers) {
77
handles[i] = handleDom(i, handlers[i], node);
82
// attach the dom events that will trigger the CE
83
function attachTriggers (node) {
84
var key = ceName(node);
85
var reg = registry[ key ] = registry[ key ] || {
87
handles : attachDomEventHandlers(domEventHandlers, node)
93
function handleDom (event, handler, node) {
94
var handle = Y.on(event, handler, node);
95
Y.after(Y.bind(afterDetach, null, node, true), handle, "detach");
99
// call this after detaching a CE handler
100
function afterDetach (node, force) {
101
var reg = registry[ ceName(node) ];
104
if (force) reg.count = 0;
105
if (reg.count <= 0) {
106
delete registry[ ceName(node) ];
107
for (var i in reg.handles) reg.handles[i].detach();
113
on : function (type, fn, el, o) {
114
var args = Y.Array(arguments, 0, true),
115
nodeList = toNodeList(el);
116
if (nodeList.size() === 0) return onAvail(el, args);
118
args[3] = o = o || ((nodeList.size() === 1) ? nodeList.item(0) : nodeList);
121
nodeList.each(function (node) {
122
var proxyHandle = attachProxy(node, args);
123
handles.push(proxyHandle);
124
// hook into the detach event to remove it from that node.
125
Y.after(Y.bind(afterDetach, null, node), proxyHandle, "detach");
128
return { evt:handles, sub:nodeList, detach:function () {
129
Y.Array.each(handles, function (h) { h.detach() });
135
// IMPLEMENTATION SPECIFIC
136
eventName = "valueChange",
137
domEventHandlers = (function () {
138
var valueHistory = {}, intervals = {}, timeouts = {};
140
function startPolling (node, e) {
141
var key = ceName(node);
144
intervals[key] = setInterval(Y.bind(poller, null, node, e), 50);
145
timeouts[key] = setTimeout(Y.bind(stopPolling, null, node), 10000);
147
function stopPolling (node) {
148
var key = ceName(node);
149
clearTimeout(timeouts[key]);
150
clearInterval(intervals[key]);
152
function poller (node, e) {
153
var key = ceName(node);
154
var value = node.get("value");
155
if (value === valueHistory[key]) return;
159
oldValue : valueHistory[key],
165
valueHistory[key] = node.get("value");
166
startPolling(node, e);
170
function keyUpHandler (e) {
171
// indications that an IME has started.
172
// poll for 10 seconds.
173
if (e.charCode === 229 || e.charCode === 197) startPolling(
177
function blurHandler (e) {
178
stopPolling(e.currentTarget);
180
function keyDownHandler (e) {
181
startPolling(e.currentTarget, e);
185
keyup : keyUpHandler,
187
keydown : keyDownHandler
190
// /IMPLEMENTATION SPECIFIC
194
Y.Env.evt.plugins[eventName] = event;
195
if (Y.Node) Y.Node.DOM_EVENTS[eventName] = event;
198
}, '3.1.2' ,{optional:['event-custom'], requires:['node-base', 'event-focus']});