rekow / panoptic

see all, do all. simple object keypath observers.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

#panoptic simple object keypath observers.

Build Status Coverage Status

##Installation ###node Add to your dependencies in package.json:

  ...
  "dependencies": {
    "panoptic": "~0.0.9",
    ...
  },
  ...

or install directly:

npm install --save panoptic

###browser Include either of the bundles in the dist/ folder of the repo, depending on whether or not you'd like it minified.

##Usage Import the panoptic module:

var panoptic = require('panoptic');

then call with an object you want to observe:

var data = {
  name: 'David Rekow',
  age: 25
};

var observable = panoptic(data);

###getting

value = observable.get('key');
value = observable.key;

Retrieve the value for a particular key via getter or object property access. If you're not sure whether the key exists before accessing, use get() to avoid a TypeError when retrieving deeply nested values:

value = observable.get('a.b.c');  // if a or b doesn't exist, returns null
value = observable.a.b.c;         // if a or b doesn't exist, throws TypeError

###setting

observable.set('key', value);
observable.key = value;

Set the value of a key in the same way. If setting a deeply nested key and you don't know whether intermediate objects exist, use set() and they will be created (think mkdir -p):

observable.set('a.b.c', value);   // if a or b doesn't exist they will be created
observable.a.b.c = value;         // if a or b doesn't exist, throws TypeError

To set multiple keys at once, simply pass an object to set():

observable.set({  // as a flat namespaced object
  'a': true,
  'b.c': 12
});
observable.set({  // as a fully-structured object - will be set as diff
  a: true,
  b: {
    c: 12
  }
});

Setting via object property syntax only works if the key has already been seen - if you're adding a new key, use set() to ensure the observation chain is set up. ###removing

observable.set('a.b', null);
observable.a.b = null;

To remove a key from an observable object simply set it to null. If the key currently points to a nested object, watchers for any existing nested properties will be invoked before removing the key:

observable = panoptic({
  a: {
    b: {
      c: 1
    }
  }
});

observable.watch('a.b.c', function (value) {
  console.log('"a.b.c" value: ' + value);
});
observable.watch('a.b.d', function (value) {
  console.log('"a.b.d" value: ' + value);
});
observable.watch('a.b', function (value) {
  console.log('"a.b" value: ' + value);
});

observable.a.b = null;

outputs

"a.b.c" value: null
"a.b" value: null

Because the key a.b.d had not yet been set, its watcher did not fire. ###replacing

observable.replace({key: 'newValue'});

Calling replace() replaces the current observed data entirely with the passed data, triggering watchers for removed, modified and added keys. This method uses remove() behind the scenes, so only watchers for existing properties will fire upon removal or modification. Any already-registered watchers for properties being added will be invoked. ###watching

observable.watch('a.b.c', function (newValue) {
  var value = this.get('c');  // 'this' is the object actually holding the value
  value === newValue;         // watcher receives the new value after it's set
});

Nested watchers will trigger parent watchers after triggering their own:

observable.watch('a', function () {
  console.log('reached "a" watcher');
});

observable.watch('a.b', function () {
  console.log('reached "a.b" watcher');
});

observable.set('a.b', 5);

outputs

reached "a.b" watcher
reached "a" watcher

###unwatching

var watcher = function (newValue) { ... };

observable.watch('key', watcher);
observable.unwatch('key', watcher);  // if watcher is passed, only it gets removed
observable.unwatch('key');           // if no watcher is passed, all get removed

That's it!

##FAQ ###why panoptic? it's super lightweight, matches whatever data access syntax you're currently using, and uses a simple but powerful sparse-tree data structure to avoid the overhead of propagation and digest cycles when dispatching change events.

###why panoptic? pan (all) + optic (seeing), derived from panopticon (the non-terrible connotations!)

Find a bug? Please file an issue!

About

see all, do all. simple object keypath observers.

License:MIT License


Languages

Language:JavaScript 94.4%Language:Makefile 5.6%