wiretap

Wiretap on your POJOs.

Wiretap.js

Wiretap on your POJOs.

Wiretap allows easy observing of nested JavaScript objects in ES5-compatible environments down to IE9. It's extracted from the observer component of Vue.js.

var myObject = {
  a: {
    b: 'c'
  },
  list: [
    { a: 1 },
    { a: 2 },
    { a: 3 }
  ]
}
 
// the default delimiter is \b to deal with path containing dots. 
Wiretap.pathDelimiter = '.'
 
var observer = Wiretap.create(myObject)
 
observer.on('set', function (pathvalue) {
  console.log(path, value)
})
 
observer.on('mutate', function (pathvaluemutation) {
  console.log(path, value, mutation)
})
 
myObject.a.= 'd'              // a.b           d 
myObject.= { b: 'e' }         // a             {...} 
myObject.list[0].= 2          // list.0.a      2 
                                // list.length   4 
myObject.list.push({ a: 4 })    // list          [...]     {Mutation} 
 
// Mutation object from last line: 
{
  method: 'push',
  args: [...],
  result: 4,
  index: 3,
  inserted: [...],
  removed: []
}

Note get events are disabled by default. To listen to them, set Wiretap.emitGet = true.

Wiretap mutates the target object, so you should only use it to watch plain Objects and Arrays - basically stuff that can be JSON.stringify-ed. It attaches a hidden $observer object to the target, and to every nested object under that target too. It also converts every property on the observed objects into ES5 accessors. A side effect of this is when inspected with console.log all you see are getter and setters. However you can simply do JSON.parse(JSON.stringify(obj)) to get around this. Hidden properties will not show up in stringified data, so observed objects are safe to be serialized for Ajax requests.

Wiretap cannot detect added or deleted properties from the object. However, every observed object is augmented with two hidden methods: $add(key, val) and $delete(key). Using these methods ensures property addition/deletion can be listened to as add and delete events on the observer.

For Arrays, all mutating methods are intercepted to emit mutate events. Directly setting an index will not trigger changes. Instead of arr[0] = something, use arr.$set(0, something). Arrays also get a convenience method $remove(), which takes either an object (checked with ===) or an index as argument.

The default path delimiter is \b. It's much likely to appear in JavaScript property names so you can turn the string path into an Array with:

var pathArray = path.split(/[\b]/)