Skip to content

Instantly share code, notes, and snippets.

@digitaljohn
Created June 3, 2012 22:26
Show Gist options
  • Save digitaljohn/2865226 to your computer and use it in GitHub Desktop.
Save digitaljohn/2865226 to your computer and use it in GitHub Desktop.
Hybrid of both the Shared State and Message Google+ hangout API features.
var SharedData = Class.extend({
// Storage area for the latest key values
_cache: {},
// Packet Signature
_packetSig: "SDP",
// The packet that gets sent via sendMessage
_packet: {k:"",v:""},
// Refernence to the timeout
_deltaTimeout: null,
_messageTimeout: null,
// Refernence to what changed
_deltaChanged: [],
_messageChanged: [],
// The last time a delta was sent
_lastDelta: 0,
// How often can the delta change (every 1 second)
_maxDeltaUpdate: 1000,
// Setup and attach listeners to the Google+ Hangout API
init: function()
{
console.log("SharedData::init");
var _this = this;
gapi.hangout.data.onStateChanged.add(function(e){
_this._onStateChanged(e);
});
gapi.hangout.data.onMessageReceived.add(function(e){
_this._onMessageReceived(e);
});
},
setValue: function(key, val)
{
// Store the value in the local cache
this._cache[key] = val;
// Store the fact that the key changed and needs to be sent via message and shared state
this._messageChanged.push(key);
this._deltaChanged.push(key);
// Set a timeout to 1 ms so if you have a script changing multiple values...
// they will cue up and be sent in a single packet via sendMessage
if( this._messageTimeout == null )
{
var _this = this;
this._messageTimeout = setTimeout(function(){
_this._sendMessage();
}, 1);
}
// Set a timeout to send the data via the shared state. Limit it!
if( this._deltaTimeout == null )
{
// Make sure it wont max out the limit... limiting the timeout to a range of 1-1000 ms.
var time = Math.max(1, this._maxDeltaUpdate - (this._now() - this._lastDelta) );
var _this = this;
this._deltaTimeout = setTimeout(function(){
_this._sendDelta();
}, time);
}
},
getValue: function(key)
{
if(this._cache[key] != undefined)
{
// Found updated key... return that
return this._cache[key];
}
else
{
// No key found... return from the Shared Data
return gapi.hangout.data.getValue( key );
}
},
_sendMessage: function()
{
// Build a message of key value pairs
var message = [];
for(var i in this._messageChanged)
{
message.push( {k:this._messageChanged[i], v:this._cache[ this._messageChanged[i]} );
}
// Clear the changed array
this._messageChanged = [];
// Send the data with a signature!
gapi.hangout.data.sendMessage( this._packetSig+":"+JSON.stringify(message) );
// Clear the timeout back to null
this._messageTimeout = null;
},
_sendDelta: function()
{
// Build a delta of key value pairs
var delta = {};
for(var i in this._deltaChanged)
{
delta[ this._deltaChanged[i] ] = this._cache[ this._deltaChanged[i] ];
}
// Clear the changed array
this._deltaChanged = [];
// Send the data!
gapi.hangout.data.submitDelta( delta );
// Clear the timeout back to null
this._deltaTimeout = null;
// Remember when it we last used submitDelta for rate limiting
this._lastDelta = this._now();
},
_onStateChanged: function(event)
{
var key;
var val;
// Loop though the added keys and update the cache
for (var i in event.addedKeys) {
key = event.addedKeys[i].key;
val = event.addedKeys[i].value;
this._updateCache(key, val);
}
},
_onMessageReceived: function(event)
{
// Return if packet does not have the valid sigature
var split = event.message.split(":");
if(split[0] != this._packetSig) return;
// Decode the packet
var packet = JSON.parse( split[1] );
// Loop though the key value pairs and update the cache
for(var i in packet)
{
this._updateCache(packet[i].k, packet[i].v);
}
},
_updateCache: function(key, val)
{
// Store the key if there is a change
if( this._cache[key] != val )
{
this._cache[key] = val;
// Dispatch the change!
// We use a core event bus to hook various parts of the application together. Roll your own however you prefer.
bus.dispatchEvent( { type:"SharedData.CHANGE", key:key, value:val } );
}
},
// Return now doen to a 1000ms accuracy.
_now: function()
{
return (new Date()).getTime();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment