var JSON;JSON||(JSON={});
(function(){function a(a){return 10>a?"0"+a:a}function b(a){c.lastIndex=0;return c.test(a)?'"'+a.replace(c,function(a){var b=h[a];return"string"===typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function d(a,e){var c,h,l,o,p=f,k,j=e[a];j&&"object"===typeof j&&"function"===typeof j.toJSON&&(j=j.toJSON(a));"function"===typeof i&&(j=i.call(e,a,j));switch(typeof j){case "string":return b(j);case "number":return isFinite(j)?""+j:"null";case "boolean":case "null":return""+j;
case "object":if(!j)return"null";f+=g;k=[];if("[object Array]"===Object.prototype.toString.apply(j)){o=j.length;for(c=0;c<o;c+=1)k[c]=d(c,j)||"null";l=0===k.length?"[]":f?"[\n"+f+k.join(",\n"+f)+"\n"+p+"]":"["+k.join(",")+"]";f=p;return l}if(i&&"object"===typeof i){o=i.length;for(c=0;c<o;c+=1)"string"===typeof i[c]&&(h=i[c],(l=d(h,j))&&k.push(b(h)+(f?": ":":")+l))}else for(h in j)Object.prototype.hasOwnProperty.call(j,h)&&(l=d(h,j))&&k.push(b(h)+(f?": ":":")+l);l=0===k.length?"{}":f?"{\n"+f+k.join(",\n"+
f)+"\n"+p+"}":"{"+k.join(",")+"}";f=p;return l}}if("function"!==typeof Date.prototype.toJSON)Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+a(this.getUTCMonth()+1)+"-"+a(this.getUTCDate())+"T"+a(this.getUTCHours())+":"+a(this.getUTCMinutes())+":"+a(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()};var e=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
c=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,f,g,h={"\u0008":"\\b","\t":"\\t","\n":"\\n","\u000c":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},i;if("function"!==typeof JSON.stringify)JSON.stringify=function(a,b,c){var e;g=f="";if("number"===typeof c)for(e=0;e<c;e+=1)g+=" ";else"string"===typeof c&&(g=c);if((i=b)&&"function"!==typeof b&&("object"!==typeof b||"number"!==typeof b.length))throw Error("JSON.stringify");return d("",
{"":a})};if("function"!==typeof JSON.parse)JSON.parse=function(a,b){function c(a,d){var e,f,g=a[d];if(g&&"object"===typeof g)for(e in g)Object.prototype.hasOwnProperty.call(g,e)&&(f=c(g,e),void 0!==f?g[e]=f:delete g[e]);return b.call(a,d,g)}var d,a=""+a;e.lastIndex=0;e.test(a)&&(a=a.replace(e,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return d=eval("("+a+")"),"function"===typeof b?c({"":d},""):d;throw new SyntaxError("JSON.parse");}})();function PlanktonRealTime(a,b,d,e){var c={},f=0,g=[],h,i=function(a){if("rn"in a){var d=c[a.rn];if(d&&(c[a.rn]=null,clearTimeout(d.timer),d.cb&&d.cb.onMessage))d.cb.onMessage(a.data)}else if("data"in a)b(a.data);else{if("error"in a)throw"A server-side error has occured: "+a.error;throw"Unrecognized message returned from server: "+planktonStringifyJSON(a);}},m=function(){var a=g;g=null;for(var b=0;b<a.length;b++)r(a[b]);d&&d()},n=function(a){null===g&&(g=[]);e&&e();a?PlanktonLogger.log("Connection shutdown command received. Shutting down..."):
(PlanktonLogger.log("Connection lost.  Reconnecting in 30000ms."),setTimeout(q,3E4))},q=function(){h=planktonGetTransportMethod(a,i,m,n)};q();var r=function(a){null===g?h.send(a):g.push(a)};this.sendRequest=function(a,b){var d=++f;r({rn:d,payload:a});var e=setTimeout(function(){var a=c[d];if(a&&(c[d]=null,a.cb&&a.cb.onTimeout))a.cb.onTimeout()},45E3);c[d]={cb:b,timer:e}}}
function planktonGetTransportMethod(a,b,d,e){return"MozWebSocket"in window||"WebSocket"in window?new PlanktonWebSockImpl(a,b,d,e):new PlanktonLongPollImpl(a,b,d,e)}
function PlanktonWebSockImpl(a,b,d,e){var c=this,f=null;PlanktonLogger.log("Connecting to ws://"+a);var a="ws://"+a,g="MozWebSocket"in window?new MozWebSocket(a):new WebSocket(a);g.onopen=function(){f=setInterval(function(){c.send({rn:0,payload:{action:"nop"}})},3E4);d()};g.onclose=function(){clearInterval(f);e()};g.onmessage=function(a){a=planktonEvalJSON(a.data);b(a)};this.send=function(a){a=planktonStringifyJSON(a,!1);g.send(a)}}
var PLANKTON_LONGPOLL_START_PARAM="start",PLANKTON_LONGPOLL_COMMAND_CB_NAME="pLPCommand",PLANKTON_LONGPOLL_DATA_CB_NAME="pRTLPCB",PLANKTON_LONGPOLL_ID_PARAM="id",PLANKTON_LONGPOLL_PW_PARAM="pw",PLANKTON_LONGPOLL_SERIAL_PARAM="ser",PLANKTON_LONGPOLL_SEGMENT_NUM_PARAM="seg",PLANKTON_LONGPOLL_TOTAL_SEGMENTS_PARAM="ts",PLANKTON_LONGPOLL_DATA_PARAM="d",PLANKTON_LONGPOLL_DISCONN_FRAME_PARAM="disconn",PLANKTON_LONGPOLL_RESET_COMMAND="reset",PLANKTON_LONGPOLL_SHUTDOWN_COMMAND="shutdown",PLANKTON_LONGPOLL_PROTO_VER_PARAM=
"v",PLANKTON_LONGPOLL_PROTO_VER_NUM="1";
function PlanktonLongPollImpl(a,b,d,e){this.KEEPALIVE_REQUEST_INTERVAL=45E3;this.MAX_PAYLOAD_SIZE=1850;var c=this;this.refreshTimer=this.myPW=this.myID=null;this.myBaseURL="http://"+a;this.currentSerial=Math.floor(1E8*Math.random());this.scriptTagHolder=new PlanktonIFrameScriptHolder(function(a,b,h){a==PLANKTON_LONGPOLL_START_PARAM?(c.myID=b,c.myPW=h,d(),c.addDisconnectPingFrame(),c.resetRefreshTimer()):a==PLANKTON_LONGPOLL_RESET_COMMAND?(c.cleanup(),e()):a==PLANKTON_LONGPOLL_SHUTDOWN_COMMAND&&(PlanktonLogger.log("Shutdown message received from server, likely due to unmatching version numbers for long-polling protocol."),
c.cleanup(),e(!0))},function(a){for(c.resetRefreshTimer();0<a.length;a++)b(a[0])},function(){c.sendRequest(null)});this.scriptTagHolder.addTag(this.myBaseURL+"?"+PLANKTON_LONGPOLL_START_PARAM+"=t&"+PLANKTON_LONGPOLL_SERIAL_PARAM+"="+this.currentSerial+"&"+PLANKTON_LONGPOLL_PROTO_VER_PARAM+"="+PLANKTON_LONGPOLL_PROTO_VER_NUM,this.currentSerial)}PlanktonLongPollImpl.prototype.cleanup=function(){clearTimeout(this.refreshTimer);this.scriptTagHolder.removeIFrameFromDOM();this.myDisconnFrame&&document.body.removeChild(this.myDisconnFrame)};
PlanktonLongPollImpl.prototype.send=function(a){a=planktonStringifyJSON(a,!1);this.sendRequest(a,!0)};PlanktonLongPollImpl.prototype.resetRefreshTimer=function(){var a=this;null!==this.refreshTimer&&clearTimeout(this.refreshTimer);this.refreshTimer=setTimeout(function(){a.sendRequest(null,!0)},this.KEEPALIVE_REQUEST_INTERVAL)};
PlanktonLongPollImpl.prototype.sendRequest=function(a,b){this.currentSerial++;var d=this.myBaseURL+"?"+PLANKTON_LONGPOLL_ID_PARAM+"="+this.myID+"&"+PLANKTON_LONGPOLL_PW_PARAM+"="+this.myPW+"&"+PLANKTON_LONGPOLL_SERIAL_PARAM+"="+this.currentSerial;if(null===a)this.scriptTagHolder.addTag(d,this.currentSerial,b);else{for(var e=PlanktonBase64Encoder.encode(a),c=[],f=0;f<e.length;f+=this.MAX_PAYLOAD_SIZE)f+this.MAX_PAYLOAD_SIZE>e?c.push(e.substring(f,e.length)):c.push(e.substring(f,f+this.MAX_PAYLOAD_SIZE));
for(e=0;e<c.length;e++)this.scriptTagHolder.addTag(d+"&"+PLANKTON_LONGPOLL_SEGMENT_NUM_PARAM+"="+e+"&"+PLANKTON_LONGPOLL_TOTAL_SEGMENTS_PARAM+"="+c.length+"&"+PLANKTON_LONGPOLL_DATA_PARAM+"="+c[e],this.currentSerial)}};
PlanktonLongPollImpl.prototype.addDisconnectPingFrame=function(){this.myDisconnFrame=document.createElement("iframe");this.myDisconnFrame.src=this.myBaseURL+"?"+PLANKTON_LONGPOLL_DISCONN_FRAME_PARAM+"=t&"+PLANKTON_LONGPOLL_ID_PARAM+"="+this.myID+"&"+PLANKTON_LONGPOLL_PW_PARAM+"="+this.myPW;this.myDisconnFrame.style.display="none";document.body.appendChild(this.myDisconnFrame)};
function PlanktonIFrameScriptHolder(a,b,d){this.myOnMessageCB=b;this.outstandingRequests=new PlanktonCountedSet;window[PLANKTON_LONGPOLL_COMMAND_CB_NAME]=a;window[PLANKTON_LONGPOLL_DATA_CB_NAME]=b;this.myOnNewPollNeededCB=d;this.myIFrame=this.createIFrame();a="<html><body><script>function "+PLANKTON_LONGPOLL_COMMAND_CB_NAME+'(c, a1, a2, a3, a4){parent.window["'+PLANKTON_LONGPOLL_COMMAND_CB_NAME+'"](c, a1, a2, a3, a4);}\nfunction '+PLANKTON_LONGPOLL_DATA_CB_NAME+'(data){parent.window["'+PLANKTON_LONGPOLL_DATA_CB_NAME+
'"](data);}\n<\/script></body></html>';this.myIFrame.doc.open();this.myIFrame.doc.write(a);this.myIFrame.doc.close()}PlanktonIFrameScriptHolder.prototype.createIFrame=function(){var a=document.createElement("iframe");a.style.display="none";document.body.appendChild(a);if(a.contentDocument)a.doc=a.contentDocument;else if(a.contentWindow)a.doc=a.contentWindow.document;else if(a.document)a.doc=a.document;return a};PlanktonIFrameScriptHolder.prototype.removeIFrameFromDOM=function(){try{for(;this.myIFrame.doc.hasChildNodes();)this.myIFrame.doc.removeChild(iframe.doc.firstChild)}catch(a){}document.body.removeChild(this.myIFrame)};
PlanktonIFrameScriptHolder.prototype.addTag=function(a,b,d){var e=this;setTimeout(function(){e.addTagHelper(a,b,d)},1)};
PlanktonIFrameScriptHolder.prototype.addTagHelper=function(a,b,d){d&&this.outstandingRequests.clear();var e=this;this.outstandingRequests.add(b);var c=this.myIFrame.doc.createElement("script");c.type="text/javascript";c.async=!0;c.src=a;c.onload=c.onreadystatechange=function(){var a=c.readyState;if(!a||"loaded"===a||"complete"===a)c.onload=c.onreadystatechange=null,c.parentNode&&(c.parentNode.removeChild(c),e.outstandingRequests.remove(b),e.outstandingRequests.isEmpty()&&e.myOnNewPollNeededCB())};
this.myIFrame.doc.body.appendChild(c)};var Plankton=function(){var a={},b;a.reset=function(){b={}};a.reset();a.getNode=function(a){var e;var c=a,a=c.indexOf("://");0<a&&(c=c.substring(a+3));var f=c.indexOf("/");if(0<f){a=c.substring(0,f);c=c.substring(f+1);e=c.indexOf("#");0<e&&(c=c.substring(0,e));f=c.indexOf("/");0<f?(e=c.substring(0,f),c=c.substring(f)):(e=c,c="/");var f=a+"/"+e,g=b[f];g||(g=new PlanktonRepo(a,e),b[f]=g);a=g;e=c}else throw"Unknown repository URL format";return a.rootNode.getNode(e)};return a}(),PlanktonRepoId=0;
function PlanktonRepo(a,b){var d=this;this.server=a;this.reponame=b;this.repoId=PlanktonRepoId++;this.rootNode=new PlanktonNode(this,"",null);this.realtime=new PlanktonRealTime(a+"/"+b,function(a){d.handleMessage(a)})}
PlanktonRepo.prototype.startListening=function(a){var b=this,d=this.rootNode.getNode(a,!0);0===d._$listenerCount&&this.realtime.sendRequest({action:"listen",path:a},{onTimeout:function(){PlanktonLogger.log("timed out on listen...")}});d._$listenerCount++;var e=!1;return function(){if(!e&&(e=!0,d._$listenerCount--,0===d._$listenerCount)){var a=d.path();b.realtime.sendRequest({action:"unlisten",path:a},{onTimeout:function(){PlanktonLogger.log("timed out on unlisten...")}})}}};
PlanktonRepo.prototype.handleMessage=function(a){PlanktonLogger.log("handleMessage",a);var b;0<=a.path.indexOf("$")?(b=a.path.replace("$",""),b=this.rootNode.getNode(b),b._$priority=a.data.payload,b.parent()._$children.move(b)):(b=this.rootNode.getNode(a.path),b._$handlePushUpdate(a))};
function PlanktonNode(a,b,d){this._$repo=a;this._$key=b;this._$parent=d;this._$listenerCount=0;this._$watchers=new PlanktonSet;this._$serverVersion=this._$serverValue=null;this._$pendingValue=void 0;this._$pendingValueFromTransaction=!1;this._$pendingPutId=null;this._$moved=this._$changed=this._$visible=this._$hasData=!1;this._$priority=0;this._$children=new PlanktonChildrenCollection;this._$windowSize=Number.MAX_VALUE;this._$windowStart=null;this.local={}}PlanktonNode.prototype.key=function(){return this._$key};
PlanktonNode.prototype.parent=function(){return this._$parent};PlanktonNode.prototype.path=function(){var a="";null!==this._$parent&&(a=this._$parent.path());return a+this._$key+"/"};PlanktonNode.prototype.prev=function(){return null===this.parent()?null:this._$prevNextHelper().prev};PlanktonNode.prototype.next=function(){return null===this.parent()?null:this._$prevNextHelper().next};
PlanktonNode.prototype._$prevNextHelper=function(){var a=null,b=null,d=0,e=this;this.parent().forEach(function(c){c===e?(e._$assert(0===d,"node found multiple times?"),d=1):0===d?a=c:1===d&&(b=c,d=2)});this._$assert(1<=d,"prev/next called on node not in window.");return{prev:a,next:b}};PlanktonNode.prototype.hasChildren=function(){var a=!1;this.forEach(function(){return a=!0});return a};
PlanktonNode.prototype.set=function(a,b){if("undefined"===typeof a)throw"PlanktonNode.set failed: Must specify a value to be set.";if(".length"===this.key()||".keys"===this.key())throw"PlanktonNode.set failed: '"+this.path()+"' is server-generated and cannot be overwritten.";this._$log("set",{path:this.path(),value:a});var d=[];this._$setInternal(a,d);if(0===d.length&&b)b();else{for(var e=planktonNewId(),c=0;c<d.length;c++)d[c]._$pendingPutId=e;var f=this;this._$putSelfToServer(function(){for(var a=
[],c=0;c<d.length;c++){var i=d[c];if(i._$pendingPutId===e)i._$pendingPutId=null,null===i._$serverVersion&&i._$setServerValue(i._$getPendingValue()),i._$getServerValue()!==i._$getPendingValue()&&a.push(i),i._$removePendingValue()}f._$raiseEventsForChangedNodes(a);b&&b()});this._$raiseEventsForChangedNodes(d)}};
PlanktonNode.prototype._$setInternal=function(a,b){if(this._$hasPendingValue()&&this._$pendingValueFromTransaction&&!Plankton._$inTransaction)throw"PlanktonNode.set failed: Value has a pending transaction already.  Can't set. [THIS IS A TEMPORARY LIMITATION.  Please email plankton@envolve.com and let us know you're hitting it.]";var d=typeof a;if("number"===d||"boolean"===d||"string"===d)this._$children.forEach(function(a){a._$setInternal(null,b)}),this._$getNodeValue()!==a&&(this._$setPendingValue(a),
b.push(this));else if("object"===d){var e={};this._$children.forEach(function(a){e[a.key()]=!0});null!==this._$getNodeValue()&&(this._$setPendingValue(null),b.push(this));for(var c in a)this.getNode(c)._$setInternal(a[c],b),delete e[c];for(var f in e)this.getNode(f)._$setInternal(null,b);this._$updateHasData()}else throw"PlanktonNode.set failed: Can't set '"+this.path()+"' to '"+a+"'.  Values must be numbers, booleans, or strings.";};
PlanktonNode.prototype._$updateHasData=function(){var a=this._$hasData,b=this;this._$hasData=!1;this._$children.forEach(function(a){if(a._$hasData)b._$hasData=!0});if(!this._$hasData)this._$hasData=null!==this._$getNodeValue();this._$hasData!==a&&null!==this.parent()&&this.parent()._$updateHasData()};
PlanktonNode.prototype.transaction=function(a,b){this._$log("transaction",{path:this.path()});var d=this;PlanktonNode._$forEachRecursive(this,function(){d._$assert(!d._$hasPendingValue(),"Can't mix transaction() and set() operations or do multiple transactions.")});var e=-1,c=!1;this._$tryTransactionIfUpToDate=function(){if(!(null!==d._$pendingPutId||-1!==e&&null!==d._$serverVersion&&d._$serverVersion<e))if(c)f(!1,[]);else{d._$log("transaction - execute update and push to server",{path:d.path(),lastestVersion:e});
var b=a(this._$getServerValAsJSON()),g=[];if("undefined"===typeof b)PlanktonNode._$forEachRecursive(d,function(a){a._$hasPendingValue()&&(a._$removePendingValue(),g.push(a))}),f(!0,g);else{d._$setInternal(b,g);if(null!==d._$serverVersion)d._$pendingPutId=1,d._$putSelfToServer(function(a){d._$pendingPutId=null;var b=Number(a.data);d._$log("transaction put response",{path:d.path(),status:a.status,version:a.data});if("success"===a.status)c=!0,e=b,d._$serverVersion>=b&&f(!1,[]);else if("versionstale"===
a.status)e=Number(a.data),d._$tryTransactionIfUpToDate();else throw"Transaction failed for some reason.";},!0);0!==g.length&&(d._$log("transaction events",{path:d.path(),changedNodes:g.length}),d._$raiseEventsForChangedNodes(g))}}};var f=function(a,c){d._$log("transaction completed",{path:d.path()});PlanktonNode._$forEachRecursive(d,function(a){a._$removePendingValue()});g.unwatch();d._$tryTransactionIfUpToDate=null;0!==c.length&&(d._$log("transaction events",{path:d.path(),changedNodes:c.length}),
d._$raiseEventsForChangedNodes(c));b&&b(a)},g=d.watchNodes(function(){});this._$tryTransactionIfUpToDate()};PlanktonNode.prototype._$setPendingValue=function(a,b){this._$pendingValue=a;this._$pendingValueFromTransaction=b;this._$updateHasData()};PlanktonNode.prototype._$getPendingValue=function(){return this._$pendingValue};PlanktonNode.prototype._$removePendingValue=function(){this._$pendingValue=void 0;this._$pendingValueFromTransaction=!1;this._$updateHasData()};
PlanktonNode.prototype._$hasPendingValue=function(){return"undefined"!==typeof this._$pendingValue};PlanktonNode.prototype._$setServerValue=function(a,b){this._$serverValue=a;if("undefined"!==typeof b)this._$serverVersion=Number(b);this._$updateHasData()};PlanktonNode.prototype._$getServerValue=function(){return this._$serverValue};PlanktonNode.prototype._$getNodeValue=function(){return this._$hasPendingValue()?this._$pendingValue:this._$serverValue};
PlanktonNode.prototype.val=function(a){if(1<arguments.length)throw"PlanktonNode.val: Takes zero or one argument.";if(a){if("function"!=typeof a)throw"PlanktonNode.val: Argument passed to val() must be a callback function to be called when the value is read from the server.";var b=this;this._$repo.realtime.sendRequest({action:"get",path:this.path()},{onMessage:function(c){if("success"===c.status)b._$handlePushUpdate(c),a(b.val());else throw"get failed for some reason! "+planktonStringifyJSON(c);},
onTimeout:function(){PlanktonLogger.log("Timed out on 'get'...")}})}if(null!==this._$getNodeValue())return this._$getNodeValue();var d={},e=0,c=!0,f=Number.NEGATIVE_INFINITY;this._$children.forEach(function(a){a._$visible&&(e++,d[a.key()]=a.val(),/^\d+$/.test(a.key())?f=Math.max(f,Number(a.key())):c=!1)});if(0===e)return null;if(c&&f<2*e){var g=[],h;for(h in d)g[h]=d[h];return g}return d};
PlanktonNode.prototype._$getServerValAsJSON=function(){if(null!==this._$getServerValue())return this._$getServerValue();var a={},b=0,d=!0,e=Number.NEGATIVE_INFINITY;this._$children.forEach(function(c){var f=c._$getServerValAsJSON();null!==f&&(b++,a[c.key()]=f,/^\d+$/.test(c.key())?e=Math.max(e,Number(c.key())):d=!1)});if(0===b)return null;if(d&&e<2*b){var c=[],f;for(f in a)c[f]=a[f];return c}return a};
PlanktonNode.prototype._$serverValWithPriorities=function(){var a=this._$getNodeValue();if(null!==a)return a;var b={},d=!0;this._$children.forEach(function(a){b[a.key()]=a._$serverValWithPriorities();b["$"+a.key()]=a.getPriority();d=!1});return d?null:b};PlanktonNode.prototype.getNode=function(a){return this._$nodeHelper((""+a).split("/"))};
PlanktonNode.prototype._$nodeHelper=function(a){if(0===a.length)return this;var b=a[0];a.splice(0,1);if(""===b)return this._$nodeHelper(a);if("."===b.substring(0,1)&&".length"!==b&&".keys"!==b)throw"PlanktonNode.getNode failed: '"+b+"' is invalid.  Keys may not begin with '.'";var d=this._$children.itemByKey(b);if(d)return d._$nodeHelper(a);b=new PlanktonNode(this._$repo,b,this);this._$children.add(b);return b._$nodeHelper(a)};
PlanktonNode.prototype.watch=function(a){return this._$watchInternal(!1,a)};PlanktonNode.prototype.watchNodes=function(a){return this._$watchInternal(!0,a)};
PlanktonNode.prototype._$watchInternal=function(a,b){var d=this._$repo.startListening(this.path()),e={callback:b,isWatchNodes:a};this._$watchers.add(e);var c=[];this.forEach(function(a){c.push(new PlanktonEvent(PlanktonEvent.NODE_ADDED,a))});0===c.length&&null!==this.val()&&c.push(new PlanktonEvent(PlanktonEvent.VALUE_CHANGED,this));0<c.length&&this._$raiseEventsToWatchers(c,[e]);var f=this;return{unwatch:function(){f._$watchers.remove(e);d()}}};
PlanktonNode.prototype.push=function(a,b){for(var d="",e=0;20>e;e++)d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".charAt(Math.floor(62*Math.random()));d=this.getNode(d);e=1E3*(new Date).getTime();Plankton._$lastPushTimestamp&&e<=Plankton._$lastPushTimestamp&&(e=Plankton._$lastPushTimestamp+1);Plankton._$lastPushTimestamp=e;d.setPriority(e);"undefined"!==typeof a&&null!==a&&d.set(a,b);return d};PlanktonNode.prototype.forEach=function(a){this._$children.forEach(function(b){if(b._$visible)return a(b)})};
PlanktonNode.prototype.remove=function(a){if(null===this._$parent)throw"Remove failed.  Can't remove root PlanktonNode.";this.set(null,a)};
PlanktonNode.prototype.setPriority=function(a){this._$priority=a;if(null===this.parent())throw"PlanktonNode.setPriority failed: You may not set a priority on the root node.";var b=this.parent()._$children.move(this),d=this.parent().path()+"$"+this.key();this._$repo.realtime.sendRequest({action:"put",path:d,data:a},{});this._$log("setPriority:put",{path:d,data:a});if(b&&this._$hasData){this._$moved=!0;for(a=this;null!==a.parent();)a.parent()._$changed=!0,a=a.parent();this._$updateTreeAndRaiseEvents()}};
PlanktonNode.prototype.getPriority=function(){return this._$priority};PlanktonNode.prototype.setLimit=function(a){this._$windowSize=a;for(a=this;null!==a;)a._$changed=!0,a=a.parent();this._$updateTreeAndRaiseEvents()};PlanktonNode.prototype.setStart=function(){throw"PlanktonNode.setStart failed: Sorry.  We haven't yet implemented this.  Please email plankton@envolve.com and let us know you want to use it.  We'll help you out!";};
PlanktonNode.prototype.setEnd=function(){throw"PlanktonNode.setEnd failed: Sorry.  We haven't yet implemented this.  Please email plankton@envolve.com and let us know you want to use it.  We'll help you out!";};PlanktonNode.prototype.removeOnDisconnect=function(){this.setOnDisconnect(null)};
PlanktonNode.prototype.setOnDisconnect=function(a){this._$repo.realtime.sendRequest({action:"onDisconnect",path:this.path(),data:a},{onMessage:function(a){if("success"!==a.status)throw"onDisconnect failed: "+planktonStringifyJSON(a.data);},onTimeout:function(){PlanktonLogger.log("timed out on onDisconnect...")}})};PlanktonNode.prototype.log=function(){PlanktonLogger.log(planktonStringifyJSON(this.val()))};
PlanktonNode.prototype._$setServerData=function(a){var b=[];this._$setServerDataInternal(a,b);this._$tryTransactionIfUpToDate&&this._$tryTransactionIfUpToDate();for(a=this;null!==a;)a._$tryTransactionIfUpToDate&&a._$tryTransactionIfUpToDate(),a=a.parent();this._$raiseEventsForChangedNodes(b)};
PlanktonNode.prototype._$setServerDataInternal=function(a,b){var d;this._$assert(null===a.payload||Number(a.version)>=this._$serverVersion,"Received server updates out of order ('"+this.path()+"' has version "+this._$serverVersion+" locally but we're receiving version "+a.version+").");d=typeof a.payload;if("number"===d||"boolean"===d||"string"===d)this._$children.forEach(function(a){a._$setServerDataInternal({payload:null,version:0},b)}),d=a.payload!=this._$getNodeValue(),this._$setServerValue(a.payload,
a.version),d&&!this._$hasPendingValue()&&b.push(this);else{var e={};this._$children.forEach(function(a){e[a.key()]=!0});d=null!==this._$getNodeValue();this._$setServerValue(null,a.version);d&&!this._$hasPendingValue()&&b.push(this);for(var c in a.payload)if("."!==c.substring(0,1))"$"===c.substring(0,1)?(this.getNode(c.substring(1))._$priority=a.payload[c].payload,this._$children.move(this.getNode(c.substring(1)))):(delete e[c],this.getNode(c)._$setServerDataInternal(a.payload[c],b));for(var f in e)this.getNode(f)._$setServerDataInternal({payload:null,
version:0},b)}};PlanktonNode.prototype._$putSelfToServer=function(a,b){var d=this.path(),e=this._$serverValWithPriorities(),c={action:"put",path:d,data:e};if(b)c.version=this._$serverVersion;this._$repo.realtime.sendRequest(c,{onMessage:function(b){a&&a(b)},onTimeout:function(){PlanktonLogger.log("timed out on put...")}});this._$log("put",{path:d,data:e})};PlanktonNode.prototype._$handlePushUpdate=function(a){this._$setServerData(a.data)};
PlanktonNode.prototype._$raiseEventsForChangedNodes=function(a){for(var b=0;b<a.length;b++)for(var d=a[b];null!==d;)d._$changed=!0,d=d.parent();this._$updateTreeAndRaiseEvents()};PlanktonNode.prototype._$updateTreeAndRaiseEvents=function(){var a=[];this._$repo.rootNode._$updateTreeAndRaiseEventsInternal(a);for(var b=0;b<a.length;b++)a[b].node._$raiseEvents(a[b].events)};
PlanktonNode.prototype._$updateTreeAndRaiseEventsInternal=function(a){if(this._$changed||this._$moved){var b=[],d=this,e=0;this._$children.forEachReverse(function(c){var f=c._$changed,g=c._$moved;c._$updateTreeAndRaiseEventsInternal(a);if(e<d._$windowSize&&c._$hasData)e++,c._$visible?f?b.push(new PlanktonEvent(PlanktonEvent.NODE_CHANGED,c)):g&&b.push(new PlanktonEvent(PlanktonEvent.NODE_MOVED,c)):(c._$visible=!0,b.push(new PlanktonEvent(PlanktonEvent.NODE_ADDED,c)));else if(c._$visible)c._$visible=
!1,b.push(new PlanktonEvent(PlanktonEvent.NODE_REMOVED,c))});this._$changed&&null!==this._$getNodeValue()&&(this._$assert(0===e,"We have a value, but also children.  Are we a leaf node or an internal node!?"),b.push(new PlanktonEvent(PlanktonEvent.VALUE_CHANGED,this)));b.reverse();a.push({node:this,events:b});this._$moved=this._$changed=!1}};PlanktonNode.prototype._$raiseEvents=function(a){var b=this._$watchers.getList();this._$raiseEventsToWatchers(a,b)};
PlanktonNode.prototype._$raiseEventsToWatchers=function(a,b){for(var d=[],e=0;e<a.length;e++){var c=[a[e].type,a[e].node.path()];a[e].type==PlanktonEvent.VALUE_CHANGED&&c.push(a[e].node.val());d.push(c)}this._$log("event raised",d);for(d=0;d<b.length;d++)if(e=b[d],e.isWatchNodes)for(e=0;e<a.length;e++)b[d].callback(a[e]);else e.callback(this.val())};
PlanktonNode.prototype._$buildLogMessage=function(){for(var a="",b=0;b<arguments.length;b++)a="object"===typeof arguments[b]?a+planktonStringifyJSON(arguments[b]):a+arguments[b],a+=" ";return this._$repo.repoId+":"+this.path()+":"+a};PlanktonNode.prototype._$log=function(){PlanktonLogger.log(this._$buildLogMessage.apply(this,arguments))};
PlanktonNode.prototype._$assert=function(){if(!arguments[0]){for(var a=[],b=1;b<arguments.length;b++)a.push(arguments[b]);planktonAssert(!1,this._$buildLogMessage.apply(this,a))}};PlanktonNode._$forEachRecursive=function(a,b){b(a);a._$children.forEach(function(a){PlanktonNode._$forEachRecursive(a,b)})};function PlanktonEvent(a,b){this.type=a;this.node=b}PlanktonEvent.NODE_ADDED="node_added";PlanktonEvent.NODE_REMOVED="node_removed";PlanktonEvent.NODE_CHANGED="node_changed";
PlanktonEvent.NODE_MOVED="node_moved";PlanktonEvent.VALUE_CHANGED="value_changed";function planktonEvalJSON(a){return"undefined"!=typeof JSON?JSON.parse(a):eval("("+a+")")}function planktonStringifyJSON(a){return JSON.stringify(a)}function PlanktonAssertException(a){this.message=a}PlanktonAssertException.prototype.toString=function(){return"PlanktonAssert: "+this.message};function planktonAssert(a,b){if(!a)throw new PlanktonAssertException(b);}var planktonNewId=function(){var a=1;return function(){return a++}}();
function planktonBinarySearch(a,b,d){for(var e=0,c=a.length-1,f,g;e<=c;)if(f=Math.floor((e+c)/2),g=d(a[f],b),0>g)e=f+1;else if(0<g)c=f-1;else return f;return e}function PlanktonSet(){this._arr=[]}PlanktonSet.prototype.add=function(a){for(var b=0;b<this._arr.length;b++)if(this._arr[b]===a)return;this._arr.push(a)};PlanktonSet.prototype.remove=function(a){for(var b=0;b<this._arr.length;b++)if(this._arr[b]===a)return a=this._arr[b],this._arr.splice(b,1),a;return null};PlanktonSet.prototype.getList=function(){return this._arr};
PlanktonSet.prototype.isEmpty=function(){return 0===this._arr.length};
function PlanktonChildrenCollection(){var a=[],b={};this.add=function(e){var c=d(e);planktonAssert(0===a.length&&0===c||a[c]!==e,"Node already exists?");a.splice(c,0,e);b[e.key()]=e};this.remove=function(e){var c=d(e);planktonAssert(0<a.length&&a[c]===e,"Node doesn't exist?");a.splice(c,1);delete b[e.key()]};this.move=function(b){for(var c=0;c<a.length&&!(a[c]===b);c++);planktonAssert(c<a.length,"Node doesn't exist?");a.splice(c,1);var f=d(b);a.splice(f,0,b);return f!==c};this.forEach=function(b){for(var c=
0;c<a.length&&!b(a[c]);c++);};this.forEachReverse=function(b){for(var c=a.length-1;0<=c&&!b(a[c]);c--);};this.itemByKey=function(a){return b[a]};var d=function(b){for(var c=0,d=a.length-1,g,h;c<=d;){g=Math.floor((c+d)/2);h=a[g];var i=b,m=h.getPriority()||0,n=i.getPriority()||0;h=m!=n?m-n:h.key()<i.key()?-1:h.key()>i.key()?1:0;if(0>h)c=g+1;else if(0<h)d=g-1;else return g}return c}}
var PlanktonBase64Encoder={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",encode:function(a){for(var b="",d,e,c,f,g,h,i=0,a=PlanktonBase64Encoder._utf8_encode(a);i<a.length;)d=a.charCodeAt(i++),e=a.charCodeAt(i++),c=a.charCodeAt(i++),f=d>>2,d=(d&3)<<4|e>>4,g=(e&15)<<2|c>>6,h=c&63,isNaN(e)?g=h=64:isNaN(c)&&(h=64),b=b+this._keyStr.charAt(f)+this._keyStr.charAt(d)+this._keyStr.charAt(g)+this._keyStr.charAt(h);return b},_utf8_encode:function(a){for(var a=a.replace(/\r\n/g,
"\n"),b="",d=0;d<a.length;d++){var e=a.charCodeAt(d);128>e?b+=String.fromCharCode(e):(127<e&&2048>e?b+=String.fromCharCode(e>>6|192):(b+=String.fromCharCode(e>>12|224),b+=String.fromCharCode(e>>6&63|128)),b+=String.fromCharCode(e&63|128))}return b}},PlanktonLogger={loggingEnabled:!1,log:function(a){"console"in window&&this.loggingEnabled&&console.log(a)}};function PlanktonCountedSet(){this.set={}}PlanktonCountedSet.prototype.add=function(a,b){this.set[a]=null!==b?b:!0};
PlanktonCountedSet.prototype.get=function(a){return this.set[a]};PlanktonCountedSet.prototype.remove=function(a){delete this.set[a]};PlanktonCountedSet.prototype.clear=function(){this.set={}};PlanktonCountedSet.prototype.isEmpty=function(){for(var a in this.set)return!1;return!0};

