Created
October 25, 2012 15:26
-
-
Save lerouxb/3953332 to your computer and use it in GitHub Desktop.
debounced-modify event on all inputs, selects and textareas
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html> | |
| <head> | |
| <title>debounced modify event</title> | |
| <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> | |
| <script> | |
| $.fn.debouncedModify = function (options) { | |
| if (!options) options = {}; | |
| if (!options.timeout) options.timeout = 250; | |
| var debounceTimers = {}; | |
| var uid = 1; | |
| function nextId(prefix) { | |
| return prefix+uid++; | |
| } | |
| /* | |
| We're being really aggressive here. We don't actually check to see if the | |
| value really changed. That's rather tricky to do and error prone, because | |
| what if you update it via code? Therefore it is probably best to check that | |
| yourself. You get way too many events, but at least they are throttled. | |
| */ | |
| this.on( | |
| 'keyup change mouseup cut paste', | |
| 'input, select, textarea', | |
| function () { | |
| var node = this; | |
| // get the id and make one if it doesn't have one | |
| var $node = $(node); | |
| var nodeId = $node.attr('id'); | |
| if (!nodeId) { | |
| nodeId = nextId(node.tagName.toLowerCase() + '-'); | |
| $node.attr('id', nodeId); | |
| } | |
| if (debounceTimers[nodeId]) clearTimeout(debounceTimers[nodeId]); | |
| debounceTimers[nodeId] = setTimeout(function () { | |
| delete debounceTimers[nodeId]; | |
| $(node).trigger('debounced-modify'); | |
| }, options.timeout); | |
| } | |
| ); | |
| }; | |
| $(document).ready(function () { | |
| // We install the delegated event handler on the document. You can probably | |
| // run this on only a specific container if you want to. | |
| $(document).debouncedModify(); | |
| $(document).on('debounced-modify', 'input', function () { | |
| var $input = $(this); | |
| var name = $input.attr('name'); | |
| $('#'+name).text($input.val()); | |
| }); | |
| // prove that this works on dynamically added elements | |
| $('body').append('<input name="bar">').append('<div id="bar"></div>'); | |
| }); | |
| </script> | |
| </head> | |
| <body> | |
| <input name="foo"> | |
| <div id="foo"></div> | |
| </body> | |
| </html> |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
'change' on inputs typically only fire on blur. 'keyup' misses things like cutting, pasting and undo/redo from the menu or selecting then dragging bits of text around. This takes care of (most) of those things centrally. It debounces so that you should only get notified during breaks in typing. The timeout defaults to 250ms and is configurable.
In a backbone app you would pronably check the value against what's in the model before saving it somewhere or doing something "expensive" with it, because this doesn't actually make sure that the value really changed. That's rather tricky to do in a generic and robust way.