Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

large refactoring - still unstable

  • Loading branch information...
commit 33332b6f3010fe76cd8dddbde575ff1b4fa4f5c6 1 parent 7fa728c
Lakshan Perera authored
View
176 public/javascripts/application.js
@@ -98,34 +98,34 @@ $(function() {
diff_worker.onmessage = function(ev){
var uuid = ev.data.id;
- var message = ev.data.changes;
+ var content = ev.data.changes;
// send the diff to server via the open socket
//if(ev.data != "send_snapshot")
- socket.send('{"type": "modify_line",' + '"uuid": ' + JSON.stringify(uuid) + ', "message":' + JSON.stringify(message) + '}');
- //else
- //takeSnapshot();
+ var line_msg = {"uuid": uuid, "content": content };
+ socket.send('{ "type": "modify_line", "message": ' + JSON.stringify(line_msg) + '}');
};
patch_worker.onmessage = function(ev){
- patch_user_id = ev.data[0];
- changed_content = ev.data[1];
+ var patching_uuid = ev.data[0];
+ var patch_user_id = ev.data[1];
+ var changed_content = ev.data[2];
+ var modifying_line = $("[data-uuid=" + patching_uuid + "]");
if(changed_content != ""){
- set_editable_content($("#editable_content"), changed_content, assigned_colors[patch_user_id]);
- previous_text = get_editable_content();
+ $(modifying_line).html(changed_content);
+
+ //highlight the line
+ highlightUserEdit(modifying_line, patch_user_id);
+
+ //apply syntax highlighting
+ applySyntaxHighlighting(modifying_line);
+
+ //update the stored line in hash
+ stored_lines[patching_uuid] = {"content": changed_content}
}
}
-// patch_worker.onmessage = function(ev){
-// changed_content = ev.data;
-//
-// if(changed_content != ""){
-// set_editable_content($("#editable_content"), changed_content, "");
-// }
-// }
-
-
var user_id;
var predefined_colors = ["#FFCFEA", "#E8FF9C", "#FFCC91", "#42C0FF", "#A7FF9E", "#7DEFFF",
"#BABDFF", "#FFD4EB", "#AAFF75", "#FF9EAB", "#DCFF91", "#8088FF"
@@ -135,6 +135,7 @@ $(function() {
var updating_process_running = false;
var playback_mode = false;
var take_diffs = true;
+ var stored_lines = {};
//Client Socket Methods
var socket = new WebSocket('ws://localhost:8080');
@@ -147,13 +148,23 @@ $(function() {
for(var user_index in received_msg["users"]){
addUser(received_msg["users"][user_index]);
}
+
+ // periodically check for available updates and apply them
+ window.setInterval(checkForUpdates, 100);
+
+ // periodically send the content for syntax highlighting
+ window.setInterval(inspectLineChanges, 99);
+
break;
case "join":
if(received_msg["payload"]["user"] != user_id)
addUser(received_msg["payload"]["user"]);
break;
+ case "leave":
+ removeUser(received_msg["payload"]["user"]);
+ break;
case "chat":
- newChatMessage(received_msg["payload"]["user"], received_msg["payload"]["message"]);
+ update_queue.push(received_msg);
break;
case "add_line":
//store the update in the queue
@@ -167,10 +178,11 @@ $(function() {
//store the update in the queue
update_queue.push(received_msg);
break;
- // case "diff":
- // //store the diff in a queue
- // diff_queue.push({'user': received_msg["payload"]["user"], 'patch':received_msg["payload"]["message"]})
- // break;
+ case "playback_done":
+ //store the update in the queue
+ update_queue.push(received_msg);
+ break;
+
default:
console.log(received_msg);
}
@@ -200,12 +212,14 @@ $(function() {
var checkForUpdates = function(){
if(update_queue.length > 0 && updating_process_running == false) {
var current_update = update_queue.shift();
-
- if(!playback_mode && (current_update["payload"]["user"] == user_id))
- return false;
- applyUpdate(current_update["channel"], current_update["payload"]);
+ if(current_update["channel"] != "chat"){
+ if(!playback_mode && (current_update["payload"]["user"] == user_id))
+ return false;
+ }
+
updating_process_running = true;
+ applyUpdate(current_update["channel"], current_update["payload"]);
}
}
@@ -223,6 +237,12 @@ $(function() {
case "remove_line":
removeLine(update);
break;
+ case "playback_done":
+ playback_mode = false;
+ break;
+ case "chat":
+ newChatMessage(update["user"], update["message"]);
+ break;
default:
console.log("invalid update");
};
@@ -233,38 +253,81 @@ $(function() {
//To add a line we need:
//it's uuid, previous line uuid and next line uuid and content
- var addLine = function(update){
+ var addLine = function(payload){
+ content = payload["message"]["content"];
+ //new line html
+ var new_line = $("<p data-uuid='" + payload["message"]["uuid"] + "'>" + content + "</p>");
+
//find the line with next uuid
+ var next_line = $("[data-uuid =" + payload["message"]["next_uuid"] + "]");
+ var previous_line = $("[data-uuid =" + payload["message"]["previous_uuid"] + "]");
+
+ if(next_line.length > 0){
//insert before next uuid
- //apply syntax highlighting
- //highlight the line
+ next_line.before(new_line);
+ }
//else find the line with previous uuid
+ else if(previous_line.length > 0){
//insert after previous uuid
- //apply syntax highlighting
- //highlight the line
- // insert as the first line
- //apply syntax highlighting
- //highlight the line
+ previous_line.after(new_line);
+ }
+ else {
+ // insert as the first line
+ $("div#editable_content div").append(new_line)
+ }
+
+ //highlight the line
+ highlightUserEdit(new_line, payload["user"]);
+
+ //apply syntax highlighting
+ applySyntaxHighlighting(new_line);
+
+ //update the stored line in hash
+ stored_lines[payload["message"]["uuid"]] = {"content": payload["message"]["content"]};
+
+ updating_process_running = false;
};
//To modify a line we need:
// the uuid of the line and diff
- var modifyLine = function(update){
+ var modifyLine = function(payload){
//find the line with uuid
+ var uuid = payload["message"]["uuid"];
+ var user_id = payload["user"];
+ var patch = payload["message"]["content"];
+
+ var current_text = $("[data-uuid=" + uuid + "]").text();
- // get the line content
- //
// send the uuid, line content and diff to patch worker
+ patch_worker.postMessage({"uuid": uuid, "patch": patch,
+ "current_text": current_text, "user_id": user_id });
+ updating_process_running = false;
};
//To remove a line we need:
// the uuid of the line
- var removeLine = function(update){
+ var removeLine = function(payload){
//find the line with uuid
+ var uuid = payload["message"]["uuid"];
+ var user_id = payload["user"];
+ var line = $("[data-uuid=" + uuid + "]");
//highlight the line
+ highlightUserEdit(line, payload["user"], function(){
+ // remove the line from the pad
+ line.remove();
+ delete stored_lines[uuid];
+ });
- // remove the line from the pad
+ updating_process_running = false;
+ };
+
+ var highlightUserEdit = function(line, user, callback){
+ line.animate({ backgroundColor: assigned_colors[user] }, 'fast')
+ .animate({ backgroundColor: "#FFFFFF" }, 'slow');
+
+ if(callback)
+ callback.call();
};
$("#editable_content").keydown(function(ev){
@@ -278,14 +341,13 @@ $(function() {
}
});
- var stored_lines = {};
var generateUUID = function(){
//get the pad id
var padid = "1";
//get the user id
- var userid = "1";
+ var userid = user_id;
//get the current timestamp (in UTC)
var d = new Date();
@@ -324,9 +386,9 @@ $(function() {
};
var applySyntaxHighlighting = function(line){
- //get the id of the line
+ //get the uuid of the line
//(jquery confuses the lines when the content changes, we can avoid it by explicitly calling the line id)
- var line_id = "#" + $(line).attr("id");
+ var line_id = "[data-uuid=" + $(line).attr("data-uuid") + "]";
//keep checking whether the line is still edited by user
$(line_id).everyTime(500, function(){
@@ -408,12 +470,10 @@ $(function() {
//send 'add line' message to server
var line_msg = { "uuid": new_uuid, "previous_uuid": prev_uuid, "next_uuid": next_uuid, "content": content }
- socket.send('{"type": "add_line", message:' + JSON.stringify(line_msg) + '}');
- console.log(stored_lines[new_uuid]);
+ socket.send('{"type": "add_line", "message":' + JSON.stringify(line_msg) + '}');
}
else {
-
//check whether this exisiting line was updated
if(stored_lines[uuid].content.length != $(this).text().length ||
stored_lines[uuid].content != $(this).text()){
@@ -443,7 +503,6 @@ $(function() {
//send 'remove line' message to server
var line_msg = {"uuid": this}
socket.send('{"type": "remove_line", "message":' + JSON.stringify(line_msg) + '}');
- console.log("removed line" + this);
});
}
}
@@ -493,21 +552,18 @@ $(function() {
// set an interval to invoke taking diffs (every 500ms)
//window.setInterval(takeDiff, 500);
- // periodically check for available patches and apply them
- //window.setInterval(checkForPatches, 100);
-
- // periodically send the content for syntax highlighting
- //window.setInterval(markAsDirty, 500);
- window.setInterval(inspectLineChanges, 500);
-
var addUser = function(id){
- new_user_li = $("<li></li>");
+ var new_user_li = $("<li id='user-" + id + "'></li>");
assigned_colors[id] = predefined_colors.pop();
new_user_li.append("<span class='user_color' style='background-color:" + assigned_colors[id] + "; color: " + assigned_colors[id] + "'>.</span>");
new_user_li.append("<span class='user_name'>User-" + id + "</span>");
$("#users_list").append(new_user_li);
- }
+ };
+
+ var removeUser = function(id){
+ $("li#user-" + id).remove();
+ };
var play_chat_sound = true;
@@ -546,10 +602,10 @@ $(function() {
//turn on the playback mode
playback_mode = true;
- //clear the pad
- previous_text = "";
- $("#editable_content").html("<li></li>");
-
+ //clear everything (pad, chat, users)
+ $("#editable_content div").html("");
+ stored_lines = {};
+ $("ul#chat_messages").html("");
}
$("#input_chat_message").keypress(function(ev){
View
129 public/javascripts/jquery.color.js
@@ -0,0 +1,129 @@
+/*
+ * jQuery Color Animations
+ * Copyright 2007 John Resig
+ * Released under the MIT and GPL licenses.
+ */
+
+(function(jQuery){
+
+ // We override the animation for all of these color styles
+ jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
+ jQuery.fx.step[attr] = function(fx){
+ if ( !fx.colorInit ) {
+ fx.start = getColor( fx.elem, attr );
+ fx.end = getRGB( fx.end );
+ fx.colorInit = true;
+ }
+
+ fx.elem.style[attr] = "rgb(" + [
+ Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0),
+ Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0),
+ Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0)
+ ].join(",") + ")";
+ }
+ });
+
+ // Color Conversion functions from highlightFade
+ // By Blair Mitchelmore
+ // http://jquery.offput.ca/highlightFade/
+
+ // Parse strings looking for color tuples [255,255,255]
+ function getRGB(color) {
+ var result;
+
+ // Check if we're already dealing with an array of colors
+ if ( color && color.constructor == Array && color.length == 3 )
+ return color;
+
+ // Look for rgb(num,num,num)
+ if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
+ return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];
+
+ // Look for rgb(num%,num%,num%)
+ if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
+ return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
+
+ // Look for #a0b1c2
+ if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
+ return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
+
+ // Look for #fff
+ if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
+ return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
+
+ // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
+ if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
+ return colors['transparent'];
+
+ // Otherwise, we're most likely dealing with a named color
+ return colors[jQuery.trim(color).toLowerCase()];
+ }
+
+ function getColor(elem, attr) {
+ var color;
+
+ do {
+ color = jQuery.curCSS(elem, attr);
+
+ // Keep going until we find an element that has color, or we hit the body
+ if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") )
+ break;
+
+ attr = "backgroundColor";
+ } while ( elem = elem.parentNode );
+
+ return getRGB(color);
+ };
+
+ // Some named colors to work with
+ // From Interface by Stefan Petre
+ // http://interface.eyecon.ro/
+
+ var colors = {
+ aqua:[0,255,255],
+ azure:[240,255,255],
+ beige:[245,245,220],
+ black:[0,0,0],
+ blue:[0,0,255],
+ brown:[165,42,42],
+ cyan:[0,255,255],
+ darkblue:[0,0,139],
+ darkcyan:[0,139,139],
+ darkgrey:[169,169,169],
+ darkgreen:[0,100,0],
+ darkkhaki:[189,183,107],
+ darkmagenta:[139,0,139],
+ darkolivegreen:[85,107,47],
+ darkorange:[255,140,0],
+ darkorchid:[153,50,204],
+ darkred:[139,0,0],
+ darksalmon:[233,150,122],
+ darkviolet:[148,0,211],
+ fuchsia:[255,0,255],
+ gold:[255,215,0],
+ green:[0,128,0],
+ indigo:[75,0,130],
+ khaki:[240,230,140],
+ lightblue:[173,216,230],
+ lightcyan:[224,255,255],
+ lightgreen:[144,238,144],
+ lightgrey:[211,211,211],
+ lightpink:[255,182,193],
+ lightyellow:[255,255,224],
+ lime:[0,255,0],
+ magenta:[255,0,255],
+ maroon:[128,0,0],
+ navy:[0,0,128],
+ olive:[128,128,0],
+ orange:[255,165,0],
+ pink:[255,192,203],
+ purple:[128,0,128],
+ violet:[128,0,128],
+ red:[255,0,0],
+ silver:[192,192,192],
+ white:[255,255,255],
+ yellow:[255,255,0],
+ transparent: [255,255,255]
+ };
+
+})(jQuery);
View
13 public/javascripts/patch_worker.js
@@ -4,14 +4,15 @@ onmessage = function(ev){
//parsed_data = JSON.parse(ev.data);
var dmp = new diff_match_patch();
- uid = ev.data[0]
- patch = ev.data[1];
- current_text = ev.data[2];
+ var uuid = ev.data["uuid"];
+ var uid = ev.data["user_id"]
+ var patch = ev.data["patch"];
+ var current_text = ev.data["current_text"];
//apply the patch
- var results = dmp.patch_apply_with_highlight(patch, current_text);
- //var results = dmp.patch_apply(patch, ct);
+ //var results = dmp.patch_apply_with_highlight(patch, current_text);
+ var results = dmp.patch_apply(patch, current_text);
// set passed data to local storage
- postMessage([uid, results[0]]);
+ postMessage([uuid, uid, results[0]]);
}
View
32 socket.js
@@ -37,7 +37,7 @@ server.addListener("connection", function(conn){
function (channel, message, subscriptionPattern) {
var output = '{"channel": "' + channel + '", "payload": ' + message + '}';
- sys.puts(output);
+ //sys.puts(output);
conn.write(output);
});
@@ -56,11 +56,6 @@ server.addListener("connection", function(conn){
// });
//
- // main_store.get('pad-snapshot', function(err, reply){
- // if(reply)
- // conn.write('{"channel": "snapshot", "payload": ' + reply + '}');
- // });
-
main_store.lrange('pad-chat', 0, -1, function(err, messages){
for(var msg_id in messages){
conn.write('{"channel": "chat", "payload": ' + messages[msg_id] + '}');
@@ -68,13 +63,11 @@ server.addListener("connection", function(conn){
});
//publish the message when joining
- conn.redis_publisher.stream.addListener("connect", function () {
- conn.redis_publisher.publish("join", JSON.stringify({"user": conn.user_id}),
- function (err, reply) {
- sys.puts(err);
- sys.puts("Published message to " +
- (reply === 0 ? "no one" : (reply + " subscriber(s).")));
- });
+ conn.redis_publisher.publish("join", JSON.stringify({"user": conn.user_id}),
+ function (err, reply) {
+ sys.puts(err);
+ sys.puts("Published message to " +
+ (reply === 0 ? "no one" : (reply + " subscriber(s).")));
});
});
});
@@ -86,7 +79,7 @@ server.addListener("connection", function(conn){
channel = message_obj["type"];
message = message_obj["message"];
timestamp = new Date().getTime();
- serialized_message = JSON.stringify({"user": this.user_id, "message": message, "timestamp": timestamp });
+ serialized_message = JSON.stringify({"user": this.user_id, "message": message, "timestamp": timestamp, "channel": channel });
//store snapshot
if(channel == "snapshot"){
@@ -95,21 +88,24 @@ server.addListener("connection", function(conn){
}
//send all the exisiting diff messages
else if(channel == "playback"){
- main_store.lrange('pad-diff', 0, -1, function(err, messages){
+ main_store.lrange('pad-1', 0, -1, function(err, messages){
for(var msg_id in messages){
log(messages[msg_id]);
- conn.write('{"channel": "diff", "payload": ' + messages[msg_id] + '}');
+ var parsed_msg = JSON.parse(messages[msg_id]); //this is a dirty hack REMOVE!
+ conn.write('{"channel":"' + parsed_msg['channel'] + '", "payload": ' + messages[msg_id] + '}');
}
+
+ //once all messages sent, send a playback complete message
+ conn.write('{"channel": "playback_done", "payload": "" }');
});
}
else {
conn.redis_publisher.publish(channel, serialized_message,
function (err, reply) {
- sys.puts(err);
sys.puts("Published message to " +
(reply === 0 ? "no one" : (reply + " subscriber(s).")));
//store the messages on main store
- main_store.rpush('pad-' + channel, serialized_message, function(err, reply){});
+ main_store.rpush('pad-1', serialized_message, function(err, reply){});
});
}
});
View
1  views/layout.html.ejs
@@ -12,6 +12,7 @@
<script type="text/javascript" src="/public/javascripts/jquery.js"></script>
<script type="text/javascript" src="/public/javascripts/prettify.js"></script>
<script type="text/javascript" src="/public/javascripts/jquery.timers.js"></script>
+ <script type="text/javascript" src="/public/javascripts/jquery.color.js"></script>
<script type="text/javascript" src="/public/javascripts/application.js"></script>
<link rel="stylesheet" href="/public/stylesheets/initial.css" type="text/css" />
Please sign in to comment.
Something went wrong with that request. Please try again.