I'm working on a fiddly web interface which is mostly built with JavaScript. Its basically one (very) large form with many sections. Each section is built based on options from other parts of the form. Whenever those options change the new values are noted in a "registry" type object and the other sections re-populate accordingly.
Having event listeners on the many form fields is starting to slow things down, and refreshing the whole form for each change would be too heavy/slow for the user.
I'm wondering whether its possible to add listeners to the registry object's attributes rather than the form elements to speed things up a bit? And, if so, could you provide/point me to some sample code?
Further information:
We can listen to input value change with JavaScript with the addEventListener method. Then we can listen for changes in the value inputted by writing: const input = document. querySelector('input') input.
The most common events you might “listen out for” are load , click , touchstart , mouseover , keydown .
To update all the values in an object: Use the Object. keys() method to get an array of the object's keys. Use the reduce() method to iterate over the array. On each iteration, return a new object that contains the values from the previous iteration and the updated value.
Event Delegation is basically a pattern to handle events efficiently. Instead of adding an event listener to each and every similar element, we can add an event listener to a parent element and call an event on a particular target using the . target property of the event object.
As far as I know, there are no events fired on Object attribute changes (edit: except, apparently, for Object.watch
).
Why not use event delegation wherever possible? That is, events on the form rather than on individual form elements, capturing events as they bubble up?
For instance (my jQuery is rusty, forgive me for using Prototype instead, but I'm sure you'll be able to adapt it easily):
$(form).observe('change', function(e) { // To identify changed field, in Proto use e.element() // but I think in jQuery it's e.target (as it should be) });
You can also capture input
and keyup
and paste
events if you want it to fire on text fields before they lose focus. My solution for this is usually:
input
on the form
.keyup
and paste
events on textarea
s (they do not fire input
on textarea
s for some reason).keyup
and paste
on the form
change
on the form
(this fires on select
s).keyup
and paste
events, compare a field's current value against its default (what its value was when the page was loaded) by comparing a text field's value
to its defaultValue
Edit: Here's example code I developed for preventing unmodified form submission and the like:
What is the best way to track changes in a form via javascript?
Thanks for the comments guys. I've gone with the following:
var EntriesRegistry = (function(){ var instance = null; function __constructor() { var self = this, observations = {}; this.set = function(n,v) { self[n] = v; if( observations[n] ) for( var i=0; i < observations[n].length; i++ ) observations[n][i].apply(null, [v, n]); } this.get = function(n) { return self[n]; } this.observe = function(n,f) { if(observations[n] == undefined) observations[n] = []; observations[n].push(f); } } return new function(){ this.getInstance = function(){ if (instance == null) { instance = new __constructor(); instance.constructor = null; } return instance; } } })(); var entries = EntriesRegistry.getInstance(); var test = function(v){ alert(v); }; entries.set('bob', 'meh'); entries.get('bob'); entries.observe('seth', test); entries.set('seth', 'dave');
Taking on-board your comments, I'll be using event delegation on the form objects to update the registry and trigger the registered observing methods.
This is working well for me so far... can you guys see any problems with this?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With