ash.js | |
---|---|
This modules provides collaboration and session history functionality. | define(['udcvis/ash/transaction', 'udcvis/ash/server', 'udcvis/queue',
'lib/backbone','underscore'],
function(ashTransaction, ashServer, queue, Backbone, _){ |
How ASH LooksRequire the module as follows:
Resources
The
| var ResourceProxy = Backbone.Model.extend({});
var ResourceProxyCollection = Backbone.Collection.extend({
model: ResourceProxy
}); |
How ASH WorksPrivate variables of the ASH singleton: | |
| var log = false; |
| var server; |
| var setServer = function(newServer){
if(server)
server.off('execute', execute);
newServer.on('execute', execute);
server = newServer;
} |
| var q = queue.create(); |
| var commit = function(transaction){
if(log)
console.log('ASH: Committing transaction: '+
JSON.stringify(transaction));
q.enqueue(currentTransaction);
_(transaction.actions).each(function(action){
_set(action.resource, action.property, action.value);
});
server.commit(transaction);
}; |
| var execute = function(transaction){
var queuedTx = q.dequeue(); |
| if(queuedTx){ |
| if(transaction.equals(queuedTx)){ |
| if(log)
console.log('ASH: Dequeued transaction: '+
JSON.stringify(transaction));
}
else{ |
| var tx = q.pop();
while(tx){
rollback(tx);
tx = q.pop();
}
rollback(queuedTx);
}
} |
| else{ |
| if(transaction.type === 'set'){
if(log)
console.log('ASH: Executing transaction from server: '+
JSON.stringify(transaction));
_set(transaction.resource,
transaction.property,
transaction.value);
}
}
};
var currentTransaction;
var _set = function(id, property, value){
var instance = instances[id];
instance.resource[property] = value;
instance.set(attributes(property, value));
};
var attributes = function(property, value){
var attributes = {};
attributes[property] = value;
return attributes;
} |
| var plugins = {}; |
| var instances = {}; |
| var proxiesByType = {};
var indexInstance = function(id, resource, proxy){
instances[id] = {
resource: resource,
proxy: proxy,
set: _(proxy.set).bind(proxy)
};
var proxies = proxiesByType[proxy.type];
if(!proxies)
proxiesByType[proxy.type] = [proxy];
else
proxies.push(proxy);
};
var createResourceProxy = function(resource, id, type){
var proxy = new ResourceProxy;
var properties = {
id:{
value: id,
writable: false
},
type:{
value: type,
writable: false
}
};
var ashProperties = [];
_(_(resource).keys()).each(function(property){
if(_(resource).has(property)){
properties[property] = {
set: function(value){
ash.set(id, property, value);
},
get: function(){
return resource[property];
}
};
ashProperties.push(property);
}
});
properties.ashProperties = {
value: ashProperties,
writable: false,
configurable: false
};
Object.defineProperties(proxy, properties);
return proxy;
}; |
Public API | var ash = { |
The
| registerPlugin: function(plugin){
plugins[plugin.type] = plugin;
},
createResource: function(type, callback){
server.genResourceId(function(id){
var resource = plugins[type].create(id);
var proxy = createResourceProxy(resource, id, type);
indexInstance(id, resource, proxy); |
Disallow third party use of Backbone's 'set' method. It it used internally in ASH to trigger events at the right time, and should not be called by third party code. | proxy.set = null;
callback(proxy);
});
},
set: function(id, property, value){
if(!currentTransaction){
currentTransaction = ashTransaction.create(); |
The JS event loop is used to delay execution.
| setTimeout(function(){
commit(currentTransaction);
currentTransaction = undefined;
}, 0);
}
currentTransaction.set(id, property, value);
},
list: function(type){
return proxiesByType[type] || [];
},
useDummyServer: function(){
setServer(ashServer.dummy);
return ashServer.dummy;
},
enableLogging: function(){
log = true;
}
};
return ash;
});
|