Skip to content
Permalink
Browse files

Added Watchable module for adding notification/watch support on query…

… result sets, refs #11537

git-svn-id: http://svn.dojotoolkit.org/src/dojo/trunk@22864 560b804f-0ae3-0310-86f3-f6aa0a117693
  • Loading branch information...
kriszyp committed Sep 13, 2010
1 parent 53f6f43 commit 4bd91a5939d4dbc8a43d673cc279bb3d39ed0895
Showing with 149 additions and 0 deletions.
  1. +81 −0 store/Watchable.js
  2. +68 −0 tests/store/Watchable.js
@@ -0,0 +1,81 @@
dojo.provide("dojo.store.Watchable");

dojo.store.Watchable = function(store){
// summary:
// The Watch store wrapper takes a store and sets a watch method on query()
// results that can be used to monitor results for changes
var callbacks = [];
// a Comet driven store could directly call notify to notify watchers when data has
// changed on the backend
var notifyAll = store.notify = function(object, existingId){
for(var i = 0, l = callbacks.length; i < l; i++){
callbacks[i](object, existingId);
}
}
var originalQuery = store.query;
store.query = function(query, options){
var results = originalQuery.apply(this, arguments);
var queryExecutor = store.queryEngine && store.queryEngine(query, options);
if(results && results.forEach){
results.watch = function(callback){
callbacks.push(function(changed, existingId){
if(query){
if(existingId){
// remove the old one
results.forEach(function(object, i){
if(store.getIdentity(object) == existingId){
results.splice(i, 1);
callback(i, existingId);
}
});
}
// add the new one
if(changed &&
// if a matches function exists, use that (probably more efficient)
(queryExecutor.matches ? queryExecutor.matches(changed) : queryExecutor([changed]).length)){
// TODO: handle paging correctly
results.push(changed);
results = queryExecutor(results);
callback(results.indexOf(changed), undefined, changed);
}
}else{
// we don't have a queryEngine, so we don't provide any index information or updates to result sets
callback(undefined, existingId, changed);
}
});
};
}
return results;
};
var inMethod;
function whenFinished(method, action){
var original = store[method];
if(original){
store[method] = function(value){
if(inMethod){
// if one method calls another (like add() calling put()) we don't want two events
return original.apply(this, arguments);
}
inMethod = true;
try{
return dojo.when(original.apply(this, arguments), function(results){
action(value);
return results;
});
}finally{
inMethod = false;
}
};
}
}
// monitor for updates by listening to these methods
whenFinished("put", function(object){
notifyAll(object, store.getIdentity(object));
});
whenFinished("add", notifyAll);
whenFinished("remove", function(id){
notifyAll(undefined, id);
});

return store;
};
@@ -0,0 +1,68 @@
dojo.provide("dojo.tests.store.Watchable");
dojo.require("dojo.store.Memory");
dojo.require("dojo.store.Watchable");

var store = dojo.store.Watchable(new dojo.store.Memory({
data: [
{id: 1, name: "one", prime: false},
{id: 2, name: "two", even: true, prime: true},
{id: 3, name: "three", prime: true},
{id: 4, name: "four", even: true, prime: false},
{id: 5, name: "five", prime: true}
]
}));
tests.register("dojo.tests.store.Watchable",
[
function testGet(t){
t.is(store.get(1).name, "one");
t.is(store.get(4).name, "four");
t.t(store.get(5).prime);
},
function testQuery(t){
var results = store.query({prime: true});
t.is(results.length, 3);
var changes = [];
results.watch(function(index, previousId, object){
changes.push({index:index, previousId:previousId, object:object});
});
var expectedChanges = [];
var two = results[0];
two.prime = false;
store.put(two); // should remove it from the array
expectedChanges.push({
"index":0,
"previousId":2
});
var one = store.get(1);
one.prime = true;
store.put(one); // should add it
expectedChanges.push({
"index":2,
object:{
id: 1,
name: "one",
prime: true
}
});
store.add({// shouldn't be added
id:6, name:"six"
});
store.add({// should be added
id:7, name:"seven", prime:true
});
expectedChanges.push({
"index":3,
"object":{
id:7, name:"seven", prime:true
}
});
store.remove(3);
expectedChanges.push({
"index":0,
"previousId":3
});
t.is(changes, expectedChanges);
}
]
);

0 comments on commit 4bd91a5

Please sign in to comment.
You can’t perform that action at this time.