Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to listen for changes to an object's attributes in JavaScript?

Tags:

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:

  • This is a plug-in for jQuery, so any functionality I can build-on from that library would be helpful but not essential.
  • Our users are using IE6/7, Safari and FF2/3, so if it is possible but only for "modern" browsers I'll have to find a different solution.
like image 757
Phillip B Oldham Avatar asked Oct 27 '08 16:10

Phillip B Oldham


People also ask

How do I listen to changes in JavaScript?

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.

What events can you listen for JavaScript?

The most common events you might “listen out for” are load , click , touchstart , mouseover , keydown .

How do you change an object in JavaScript?

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.

What is event delegation in JavaScript?

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.


2 Answers

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:

  1. Gecko/Webkit-based browsers: observe input on the form.
  2. Also in Webkit-based browsers: observe keyup and paste events on textareas (they do not fire input on textareas for some reason).
  3. IE: observe keyup and paste on the form
  4. Observe change on the form (this fires on selects).
  5. For 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?

like image 146
eyelidlessness Avatar answered Sep 22 '22 20:09

eyelidlessness


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?

like image 24
Phillip B Oldham Avatar answered Sep 21 '22 20:09

Phillip B Oldham