b39897a381c2203466da5568bfd2862a54a81311Adam MooreAdds a synthetic `valueChange` event that fires when the `value` property of an
b39897a381c2203466da5568bfd2862a54a81311Adam Moore`<input>` or `<textarea>` node changes as a result of a keystroke, mouse
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Mooreoperation, or input method editor (IME) input event.
87d6b0a14cce52c4faa4b78fc9878eb553dab0d5Adam Moore YUI().use('event-valuechange', function (Y) {
0bc189b2acbd7c4b5af63eded0c4289e224676b7Adam Moore Y.one('#my-input').on('valueChange', function (e) {
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore Y.log('previous value: ' + e.prevVal);
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore Y.log('new value: ' + e.newVal);
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore@module event-valuechange
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam MooreProvides the implementation for the synthetic `valueChange` event. This class
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Mooreisn't meant to be used directly, but is public to make monkeypatching possible.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore YUI().use('event-valuechange', function (Y) {
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore Y.one('#my-input').on('valueChange', function (e) {
b39897a381c2203466da5568bfd2862a54a81311Adam Moore Y.log('previous value: ' + e.prevVal);
b39897a381c2203466da5568bfd2862a54a81311Adam Moore Y.log('new value: ' + e.newVal);
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore@class ValueChange
43692b3f865f1b1c970aedb2b96392482bd1fe3eAdam Moore// Just a simple namespace to make methods overridable.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore // -- Static Constants -----------------------------------------------------
ff8e78b59d58eeca64349dff85a486594bbfa65bAdam Moore Interval (in milliseconds) at which to poll for changes to the value of an
b39897a381c2203466da5568bfd2862a54a81311Adam Moore element with one or more `valueChange` subscribers when the user is likely
43692b3f865f1b1c970aedb2b96392482bd1fe3eAdam Moore to be interacting with it.
b39897a381c2203466da5568bfd2862a54a81311Adam Moore @property POLL_INTERVAL
43692b3f865f1b1c970aedb2b96392482bd1fe3eAdam Moore @type Number
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore Timeout (in milliseconds) after which to stop polling when there hasn't been
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore any new activity (keypresses, mouse clicks, etc.) on an element.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore @property TIMEOUT
b39897a381c2203466da5568bfd2862a54a81311Adam Moore @type Number
b39897a381c2203466da5568bfd2862a54a81311Adam Moore @default 10000
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore // -- Protected Static Methods ---------------------------------------------
b39897a381c2203466da5568bfd2862a54a81311Adam Moore Called at an interval to poll for changes to the value of the specified
0bc189b2acbd7c4b5af63eded0c4289e224676b7Adam Moore @method _poll
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore @param {Node} node Node to poll.
b39897a381c2203466da5568bfd2862a54a81311Adam Moore @param {Object} options Options object.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore @param {EventFacade} [options.e] Event facade of the event that
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore initiated the polling.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore var domNode = node._node, // performance cheat; getValue() is a big hit when polling
b39897a381c2203466da5568bfd2862a54a81311Adam Moore vcData = node._data && node._data[DATA_KEY], // another perf cheat
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore Y.log('_poll: node #' + node.get('id') + ' disappeared; stopping polling and removing all notifiers.', 'warn', 'event-valuechange');
0bc189b2acbd7c4b5af63eded0c4289e224676b7Adam Moore currentTarget: (event && event.currentTarget) || node,
0263b559dcd210a19a22676b25ecbcac81d1692cAdam Moore Y.Object.each(vcData.notifiers, function (notifier) {
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore Restarts the inactivity timeout for the specified node.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore @method _refreshTimeout
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore @param {Node} node Node to refresh.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore @param {SyntheticEvent.Notifier} notifier
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore // The node may have been destroyed, so check that it still exists
0bc189b2acbd7c4b5af63eded0c4289e224676b7Adam Moore // before trying to get its data. Otherwise an error will occur.
b39897a381c2203466da5568bfd2862a54a81311Adam Moore Y.log('_stopPolling: node disappeared', 'warn', 'event-valuechange');
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore // If we don't see any changes within the timeout period (10 seconds by
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore // default), stop polling.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore Y.log('timeout: #' + node.get('id'), 'info', 'event-valuechange');
87d6b0a14cce52c4faa4b78fc9878eb553dab0d5Adam Moore Y.log('_refreshTimeout: #' + node.get('id'), 'info', 'event-valuechange');
b39897a381c2203466da5568bfd2862a54a81311Adam Moore Begins polling for changes to the `value` property of the specified node. If
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore polling is already underway for the specified node, it will not be restarted
0263b559dcd210a19a22676b25ecbcac81d1692cAdam Moore unless the `force` option is `true`
ae1f7ed14ee90e037ce01ce4384fda0a7102b4f2Adam Moore @method _startPolling
a3e6db667fcd33ac653355e76d3660ecf232193bJeff Craig @param {Node} node Node to watch.
a3e6db667fcd33ac653355e76d3660ecf232193bJeff Craig @param {SyntheticEvent.Notifier} notifier
a3e6db667fcd33ac653355e76d3660ecf232193bJeff Craig @param {Object} options Options object.
a3e6db667fcd33ac653355e76d3660ecf232193bJeff Craig @param {EventFacade} [options.e] Event facade of the event that
a3e6db667fcd33ac653355e76d3660ecf232193bJeff Craig initiated the polling.
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore @param {Boolean} [options.force=false] If `true`, polling will be
1b298c6f0ef597aa4ab0b8bcb25430b6c9a87749Adam Moore restarted even if we're already polling this node.
eb86457f85638a9eb7c4d5f84eb367d24061abfbAdam Moore _startPolling: function (node, notifier, options) {
eb86457f85638a9eb7c4d5f84eb367d24061abfbAdam Moore Y.log('_startPolling: aborting poll on #' + node.get('id') + ' -- not an input or textarea', 'warn', 'event-valuechange');
87d6b0a14cce52c4faa4b78fc9878eb553dab0d5Adam Moore // Don't bother continuing if we're already polling this node, unless
0bc189b2acbd7c4b5af63eded0c4289e224676b7Adam Moore // `options.force` is true.
0bc189b2acbd7c4b5af63eded0c4289e224676b7Adam Moore VC._stopPolling(node, notifier); // restart polling, but avoid dupe polls
3c245663d1bfadc0536b538247884c0667cc9313Adam Moore // Poll for changes to the node's value. We can't rely on keyboard
3c245663d1bfadc0536b538247884c0667cc9313Adam Moore // events for this, since the value may change due to a mouse-initiated
b39897a381c2203466da5568bfd2862a54a81311Adam Moore // paste event, an IME input event, or for some other reason that
3c245663d1bfadc0536b538247884c0667cc9313Adam Moore // doesn't trigger a key event.
3c245663d1bfadc0536b538247884c0667cc9313Adam Moore Y.log('_startPolling: #' + node.get('id'), 'info', 'event-valuechange');
if (notifier) {
if (!vcData) {
vcData = {};
force: true
callbacks = {
if (filter) {
notifier);
config = {
emitFacade: true