diff --git a/src/static/js/broadcast_slider.js b/src/static/js/broadcast_slider.js
index 659a07374..35da14198 100644
--- a/src/static/js/broadcast_slider.js
+++ b/src/static/js/broadcast_slider.js
@@ -52,65 +52,6 @@ function init(connection, fireWhenAllScriptsAreLoaded)
$('#editorcontainerbox').css({marginTop: height});
}, 600);
- function setAuthors(authors)
- {
- var authorsList = $("#authorsList");
- authorsList.empty();
- var numAnonymous = 0;
- var numNamed = 0;
- var colorsAnonymous = [];
- _.each(authors, function(author)
- {
- var authorColor = clientVars.colorPalette[author.colorId] || author.colorId;
- if (author.name)
- {
- if (numNamed !== 0) authorsList.append(', ');
-
- $('')
- .text(author.name || "unnamed")
- .css('background-color', authorColor)
- .addClass('author')
- .appendTo(authorsList);
-
- numNamed++;
- }
- else
- {
- numAnonymous++;
- if(authorColor) colorsAnonymous.push(authorColor);
- }
- });
- if (numAnonymous > 0)
- {
- var anonymousAuthorString = html10n.get("timeslider.unnamedauthors", { num: numAnonymous });
-
- if (numNamed !== 0){
- authorsList.append(' + ' + anonymousAuthorString);
- } else {
- authorsList.append(anonymousAuthorString);
- }
-
- if(colorsAnonymous.length > 0){
- authorsList.append(' (');
- _.each(colorsAnonymous, function(color, i){
- if( i > 0 ) authorsList.append(' ');
- $(' ')
- .css('background-color', color)
- .addClass('author author-anonymous')
- .appendTo(authorsList);
- });
- authorsList.append(')');
- }
-
- }
- if (authors.length === 0)
- {
- authorsList.append(html10n.get("timeslider.toolbar.authorsList"));
- }
-
- fixPadHeight();
- }
-
// assign event handlers to html UI elements after page load
//$(window).load(function ()
fireWhenAllScriptsAreLoaded.push(function()
diff --git a/src/static/js/revisioncache.js b/src/static/js/revisioncache.js
index 2164dbe7f..56311cdaf 100644
--- a/src/static/js/revisioncache.js
+++ b/src/static/js/revisioncache.js
@@ -152,6 +152,13 @@ $.Class("RevisionCache",
this.head_revision = this.getRevision(head_revnum || 0);
this.loader.start();
},
+ /**
+ * Get the head revision.
+ * @returns {Revision} - the head revision.
+ */
+ getHeadRevision: function () {
+ return this.head_revision;
+ },
/**
* Get a Revision instance for the specified revision number.
* If we don't yet have a Revision instance for this revision, create a
@@ -171,6 +178,18 @@ $.Class("RevisionCache",
}
return revision;
},
+ /**
+ * Add a new revision at the head.
+ * @param {number} revnum - the revision number of the new revision.
+ * @param {string} forward - the forward changeset to get here from previous head.
+ * @param {string} reverse - the reverse changeset.
+ * @param {string} timedelta - the time difference.
+ */
+ appendHeadRevision: function (revnum, forward, reverse, timedelta) {
+ this.addChangesetPair(this.head_revision.revnum, revnum, forward, reverse, timedelta);
+ this.head_revision = this.getRevision(revnum);
+ //TODO: render it if we are currently at the head_revision?
+ },
/**
* Links two revisions, specified by from and to with the changeset data
* in value and reverseValue respectively.
@@ -448,6 +467,7 @@ Thread("ChangesetLoader",
* Enqueue a request for changesets. The changesets will be retrieved
* asynchronously.
* @param {number} start - The revision from which to start.
+ *
* @param {number} granularity - The granularity of the changesets. If this
* is 1, the response will include changesets which
* can be applied to go from revision r to r+1.
@@ -678,6 +698,7 @@ $.Class("PadClient",
*/
updateAuthors: function (author_info) {
var authors = author_info;
+ console.log("[updateAuthors]: ", authors);
for (var authorid in authors) {
if (authorid in this.authors) {
// just dispose of existing ones instead of trying to update existing
@@ -689,6 +710,34 @@ $.Class("PadClient",
author.addStyleRule(this.dynamicCSS);
}
},
+ /**
+ * Merge a foreign (forward) changeset into our data. This involves rebuilding
+ * the forward changeset in our apool and building a reverse changeset.
+ * This is used to move new upstream changesets/revisions into our apool context.
+ * @param {string} changeset - The foreign changeset to merge
+ * @param {object} apool - The apool for that changeset
+ * @returns {object} - A values object with forward and reverse changesets.
+ */
+ mergeForeignChangeset: function (changeset, apool) {
+ var values = {};
+ values.forward = libchangeset.moveOpsToNewPool(
+ changeset,
+ (new AttribPool()).fromJsonable(apool),
+ this.apool
+ );
+ var reverseValue = libchangeset.inverse(
+ changeset,
+ this.divs,
+ this.alines,
+ this.apool
+ );
+ values.reverse = libchangeset.moveOpsToNewPool(
+ reverseValue,
+ (new AttribPool()).fromJsonable(apool),
+ this.apool
+ );
+ return values;
+ },
/**
* Get a div jquery element for a given attributed text line.
* @param {string} text - The text content of the line.
diff --git a/src/static/js/revisionslider.js b/src/static/js/revisionslider.js
index fd2521c08..84d2a9f4c 100644
--- a/src/static/js/revisionslider.js
+++ b/src/static/js/revisionslider.js
@@ -98,8 +98,10 @@ $.Class("RevisionSlider",
var keepPlaying = function (current_revnum) {
if (current_revnum == _this.connection.getHeadRevision())
_this.is_playing = false;
- if (!_this.is_playing)
+ if (!_this.is_playing) {
+ _this.render();
return;
+ }
setTimeout(function () {
_this.goToRevision(current_revnum + 1, keepPlaying);
}, RevisionSlider.PLAYBACK_DELAY);
@@ -113,6 +115,7 @@ $.Class("RevisionSlider",
*/
render: function () {
this.elements.revision_label.html(html10n.get("timeslider.version", { "version": this.revision_number }));
+ this.slider.setMax(this.connection.getHeadRevision());
this.slider.setValue(this.revision_number);
window.location.hash = "#" + this.revision_number;
this.setTimestamp(this.timestamp);
diff --git a/src/static/js/timeslider.js b/src/static/js/timeslider.js
index cb23f8edc..b0ae00124 100644
--- a/src/static/js/timeslider.js
+++ b/src/static/js/timeslider.js
@@ -169,6 +169,15 @@ SocketClient("AuthenticatedSocketClient",
return this;
},
+ /**
+ * Dispatch COLLABROOM messages.
+ * @param {object} data - The data received from the server.
+ */
+ handle_COLLABROOM: function(data) {
+ //console.log("[authsocket_client] handle_COLLABROOM: ", data);
+ this.dispatchMessage(data.type, data);
+ },
+
}
);
@@ -186,13 +195,9 @@ AuthenticatedSocketClient("TimesliderClient",
this.sendMessage("CLIENT_READY", {}, function() { console.log("CLIENT_READY sent");});
},
- // ------------------------------------------
- // Handling events
- handle_CLIENT_VARS: function(data) {
- console.log("[timeslider_client] handle_CLIENT_VARS: ", data);
- this.clientVars = data;
+ initialize: function (clientVars) {
+ this.clientVars = clientVars;
var collabClientVars = this.clientVars.collab_client_vars;
- this.current_revision = this.head_revision = collabClientVars.rev;
this.savedRevisions = this.clientVars.savedRevisions;
this.revisionCache = new RevisionCache(this, collabClientVars.rev || 0);
@@ -214,11 +219,52 @@ AuthenticatedSocketClient("TimesliderClient",
this.ui = new RevisionSlider(this, $("#timeslider-top"));
},
- //TODO: handle new revisions, authors etc.
- handle_COLLABROOM: function(data) {
- console.log("[timeslider_client] handle_COLLABROOM: ", data);
+ // ------------------------------------------
+ // Handling events
+ handle_CLIENT_VARS: function(data) {
+ console.log("[timeslider_client] handle_CLIENT_VARS: ", data);
+ this.initialize(data);
},
+ /**
+ * Handle USER_NEWINFO messages, which let us know that a (new) user
+ * has connected to this pad.
+ * @param {object} data - the data received from the server.
+ */
+ handle_USER_NEWINFO: function (data) {
+ console.log("[timeslider_client] handle_USER_NEWINFO: ", data.userInfo);
+ //TODO: we might not want to add EVERY new user to the users list,
+ //possibly only active users?
+ var authors = {};
+ authors[data.userInfo.userId] = data.userInfo;
+ this.padClient.updateAuthors(authors);
+ this.ui.render();
+ },
+
+ /**
+ * Handle USER_LEAVE messages, which lets us know that a user has left the
+ * pad.
+ * @param {object} data - The data received from the server.
+ */
+ handle_USER_LEAVE: function (data) {
+ console.log("[timeslider_client] handle_USER_LEAVE ", data.userInfo);
+ },
+
+ /**
+ * Handle NEW_CHANGES messages, which lets us know that a new revision has
+ * been added to the pad.
+ * @param {object} data - The data received from the server.
+ */
+ handle_NEW_CHANGES: function (data) {
+ console.log("[timeslider_client] handle_NEW_CHANGES: ", data);
+ var changesets = this.padClient.mergeForeignChangeset(data.changeset, data.apool);
+ //TODO: handle calculation of real timedela based on currenttime
+ //TODO: deal with author?
+ this.revisionCache.appendHeadRevision(data.newRev, changesets.forward, changesets.reverse, data.timeDelta);
+ this.ui.render();
+ },
+
+
/**
* Go to the specified revision number. This abstracts the implementation
* of the actual goToRevision in the padClient.
@@ -249,7 +295,7 @@ AuthenticatedSocketClient("TimesliderClient",
* @return {Revision} - the head revision.
*/
getHeadRevision: function () {
- return this.head_revision;
+ return this.revisionCache.getHeadRevision().revnum;
},
}
);