glue.js
is a key-value observing library for Javascript. glue.js
supports both
assigned and computed properties, nested in an abitrarily deep object graph.
Given the following object:
var targetObject = { v1: '' };
The target
object can be passed to the Glue constructor to create an instance
of Glue
.
var glue = new Glue(targetObject);
glue.addObserver("*", function() {
console.log('Target object changed.');
});
glue.set('v1', 'a value'); // 'Target object changed.'
In the example above, "Target object changed."
is logged on the console when
the value of v1
changed by the set
operator.
For more examples, please see the specs directory.
###Keys Keys are a core concept in Glue, for both observers and operations (ie: set).
var target = {
name: "Felix",
contact: {
phone: "555-555-5555",
email: "felix@edgecase.com"
}
}
var glue = new Glue(target);
glue.addObserver("", function(message) {
// callback will be triggered on any modification
// ex: glue.set("name", "foo");
// ex: glue.set("contact.email", "foo@edgecase.com");
});
glue.addObserver("contact", function(message) {
// callback will be triggered on any modification to the contact property
// ex: glue.set("contact", {});
// ex: glue.set("contact.email", "foo@edgecase.com");
// callback will not be triggered on modification of other properties
// ex: glue.set("name", "foo");
});
glue.addObserver("contact.email", function(message) {
// callback will be triggered on any modification to the email property of the contact object.
// ex: glue.set("contact.email", "foo@edgecase.com");
// callback will not be triggered on modification of other properties
// ex: glue.set("contact.phone", "123-456-7890");
});
####Array Specific Keys Assume the following target
var target1 = [1, 2, 3, 4, 5];
var glue = new Glue(target1);
glue.addObserver('[2]', function(message) {
// callback is executed only when a change occurs to the element at index 2 of the array.
});
glue.addObserver('[]', function(message) {
// callback is executed for every element that changes in the array.
});
####Additional Examples
var target = { v1: { arr1: [ { v2: { arr2: [ 'something' ] } } ] } };
var glue = new Glue(target);
The following keys can be used:
'v1.arr1[0].v2.arr2[0]',
'v1.arr1[0].v2.arr2[]',
'v1.arr1[0].v2.arr2',
'v1.arr1[0].v2',
'v1.arr1[0]',
'v1.arr1[]',
'v1.arr1',
'v1',
'*'
Note that generics []
can only be at the end of the key.
Example: 'v1.arr1[0].arr2[]'
is legal, but 'v1.arr1[].arr2[]'
is not
##Constructor
new Glue(targetObject);
targetObject: the object that will be observed by Glue
.
##addObserver
glue.addObserver([key(s):operation(s)], [context], callback);
key(s) (optional): specifies the key or index that will be observed by the observer.
operation(s) (optional): restricts the callback's execution for a particular operation. (push, pop, etc.)
context (optional): the context which the callback is to be executed. By default, callbacks are
executed in the context of the target
object.
callback: the function to be executed when the observer is notified. Callbacks are passed a
message parameter that contains information about what changed on the key
being listened to.
###Examples
Setting a listen for a key:
glue.addObserver('v1', callback);
Setting a observer for multiple keys:
glue.addObserver('v1, v2', callback);
Setting a observer for a specific operation:
glue.addObserver('v1:set', function(message) {
// callback
});
Setting a observer for multiple operations:
glue.addObserver('v1:set, v2:push, :insert', function(message) {
// callback
});
###Context
By default all callbacks are executed in the context
of the target
object, but can be specified by following:
var myContext = { a: ''};
glue.addObserver(myContext, function(message) {
// "this" in side the callback is myContext
this.a = 'context';
});
When the callback above is executed, myContext
will have the value { a: 'context' }
The context can be used in conjunction with keys and operations as follows:
glue.addObserver('v1:set', context, function(message) {
// callback
});
The example below demonstrates context.
var context = { myWord: 'Oh my' },
target = { v1: '' },
glue = new Glue(target);
glue.addObserver(context, function(message) {
this.myWord = message.value;
});
glue.set('v1', 'Hello');
console.log(context); // { myWord: 'Hello' }
###Messages A message object is passed to the observer callback function.
####Basic Messages
var messages = [],
target1 = { foo: "bar" },
glue = new Glue(target1);
glue.addObserver('*', function(msg) {
console.log(message);
});
glue.set('foo', 'baz');
// Output
// {
// value: "baz",
// operation: 'set'
// }
####Array Specific messages
Messages content depend on the type of key is assigned to the observer.
var message,
target1 = { arr: [1, 2, 3, 4, 5] },
glue = new Glue(target1);
glue.addObserver('arr[2]', function(msg) {
message = msg;
});
glue.set('arr[2]', 9);
console.log(message); // [{ value: 9, operation: 'set' }]
On the other hand:
var message,
target1 = { arr: [1, 2, 3, 4, 5] },
glue = new Glue(target1);
glue.addObserver('arr[]', function(msg) {
message = msg;
});
glue.set('arr[2]', 9);
console.log(message); // { value: 9, index: 2, operation: 'set' }
And directly to the target
:
var messages = [],
target1 = { arr: [1, 2, 3, 4, 5] },
glue = new Glue(target1);
glue.addObserver('*', function(msg) {
messages.push(msg);
});
glue.set('arr[2]', 9);
console.log(message);
// {
// value: { arr: [ 1, 2, 9, 4, 5 ] },
// operation: 'set'
// }
var messages = [],
target1 = [1, 2, 3, 4, 5],
glue = new Glue(target1);
glue.addObserver('[]', function(msg) {
messages.push(msg);
});
glue.filter(function(num) {
return num % 2 === 0;
});
console.log(messages)
// ------------------------------- messages ---------------------------------
// [
// { value: undefined, index: 4, operation: 'filter' },
// { value: undefined, index: 3, operation: 'filter' },
// { value: undefined, index: 2, operation: 'filter' },
// { value: 4, index: 1, operation: 'filter' },
// { value: 2, index: 0, operation: 'filter' }
// ];
// --------------------------------------------------------------------------
##removeObserver
glue.addObserver([key(s):operation(s))], [context]);
key(s) (optional): the key to be removed
operation(s) (optional): the operation to be removed
context (optional): the context to be removed
Example
glue.removeObserver('key');
glue.removeObserver('key1, key2');
glue.removeObserver('key1, key2:operation');
glue.removeObserver(':operation');
glue.removeObserver(':operation1, operation2');
glue.removeObserver('key:operation');
glue.removeObserver('key:operation, operation2');
glue.removeObserver('key1, key2:operation, operation2');
glue.removeObserver('key', context);
glue.removeObserver(':operation', context);
glue.removeObserver('key1, key2:operation', context);
glue.removeObserver('key:operation1, operation2', context);
glue.removeObserver('key1, key2:operation, operation2', context);
##set
glue.set(key, value);
Example:
var glue = new Glue({ v1: '' });
glue.set('v1', 'something');
console.log(glue.target); // { 'v1', 'something' }
##remove
glue.remove(key);
Example:
var glue = new Glue({ v1: 'something' });
glue.remove('v1'); // 'something'
console.log(glue.target); // {}
##push
glue.push([key], value);
Example:
var glue = new Glue([1,2,3]);
glue.push(4)
console.log(glue.target); // [1,2,3,4]
##pop
glue.pop([key]);
Example:
var glue = new Glue([1,2,3]);
glue.pop() // 4
console.log(glue.target); // [1,2,3]
##insert
glue.insert([key], index, value);
Example:
var glue = new Glue([1,2,3]);
glue.insert(1, 9);
console.log(glue.target); // [1, 9, 2, 3]
##filter
glue.filter([key], iterator);
Example:
var glue = new Glue([1,2,3,4,5]);
glue.filter(function(num) {
return num % 2 === 0;
}); // [2,4]
console.log(glue.target); // [2, 4]
###sortBy
glue.sortBy([key], iterator);
Example
var glue = new Glue(_.shuffle(['1elem', '2elem', '3elem', '4elem' ,'5elem']));
glue.sortBy(function(elem) { return parseInt(elem) });
console.log(glue.target); //['1elem', '2elem', '3elem', '4elem' ,'5elem']
##swap
glue.swap(key1, key2);
Example
var glue = new Glue({ v1: '', v2: { v3: 'hello' }});
glue.swap('v1', 'v2.v3');
console.log(glue.target); //{ v1: 'hello', v2: { v3: '' }}