Created
April 7, 2011 22:05
-
-
Save Wizek/908859 to your computer and use it in GitHub Desktop.
Back end server code, and client code in the html file for the truly real time demo app
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title></title> | |
<script type="text/javascript" src="/js/LearnBoost-Socket.IO-ec02373/socket.io.js"></script> | |
<script type="text/javascript" src="/js/diff_match_patch_20110217/diff_match_patch_uncompressed.js"></script> | |
<script type="text/javascript" src="/js/jquery-1.5.js"></script> | |
<style type="text/css" media="screen"> | |
html{ | |
padding:20px | |
} | |
textarea{ | |
} | |
div#content{ | |
-webkit-user-modify: read-write-plaintext-only | |
; white-space: pre-wrap | |
; width:500px | |
; height: 200px | |
; background: #EEE | |
; border: #999 solid 2px | |
; padding: 1ex | |
; border-radius: 5px | |
} | |
</style> | |
<script> | |
var socket = new io.Socket("localhost") | |
//////////////////////////////////////////////////////////////////////////////// | |
, dmp = new diff_match_patch() | |
socket.connect(); | |
socket.on('connect', function(){ console.log("connected") }) | |
socket.on('disconnect', function(){ console.log("dc'ed") }) | |
socket.on('message', function(m){ | |
$ta = $('#content') | |
//$ta.css('borderColor', 'yellow') | |
//setTimeout(function() {$ta.css('borderColor', '#999')}, 100) | |
console.log("msgReceived: \""+m+"\"") | |
//saveSelection() | |
$ta.html(m.m) | |
$('span#info').text("" + m.u + " (" + new Date(m.t).toLocaleString() + ")") | |
//restoreSelection() | |
}) | |
$(init) | |
function init () { | |
//setInterval(function() { | |
// $ta = $('#content') | |
// var sel = getInputSelection($ta.get(0)); | |
// $ta.val(Math.random()) | |
// setInputSelection($ta.get(0), sel.start, sel.end); | |
//}, 1000) | |
$("#content").keyup(function(e) { | |
var $self = $(this) | |
, val = $self.html() | |
//, nick = $('input#nick').val() | |
//$self.val("") | |
if (val != window.val) { | |
window.val = val | |
var out = {} | |
out.m = val | |
out.u = $('#name').val() || null | |
socket.send(out) | |
} | |
}) | |
} | |
/*\ | |
* Experiments with caret positioning | |
\*/ | |
// http://stackoverflow.com/questions/3286595/update-textarea-value-but-keep-cursor-position | |
function getInputSelection(el) { | |
var start = 0, end = 0, normalizedValue, range, | |
textInputRange, len, endRange; | |
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") { | |
start = el.selectionStart; | |
end = el.selectionEnd; | |
} else { | |
range = document.selection.createRange(); | |
if (range && range.parentElement() == el) { | |
len = el.value.length; | |
normalizedValue = el.value.replace(/\r\n/g, "\n"); | |
// Create a working TextRange that lives only in the input | |
textInputRange = el.createTextRange(); | |
textInputRange.moveToBookmark(range.getBookmark()); | |
// Check if the start and end of the selection are at the very end | |
// of the input, since moveStart/moveEnd doesn't return what we want | |
// in those cases | |
endRange = el.createTextRange(); | |
endRange.collapse(false); | |
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { | |
start = end = len; | |
} else { | |
start = -textInputRange.moveStart("character", -len); | |
start += normalizedValue.slice(0, start).split("\n").length - 1; | |
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { | |
end = len; | |
} else { | |
end = -textInputRange.moveEnd("character", -len); | |
end += normalizedValue.slice(0, end).split("\n").length - 1; | |
} | |
} | |
} | |
} | |
return { | |
start: start, | |
end: end | |
}; | |
} | |
function offsetToRangeCharacterMove(el, offset) { | |
return offset - (el.value.slice(0, offset).split("\r\n").length - 1); | |
} | |
function setInputSelection(el, startOffset, endOffset) { | |
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") { | |
el.selectionStart = startOffset; | |
el.selectionEnd = endOffset; | |
} else { | |
var range = el.createTextRange(); | |
var startCharMove = offsetToRangeCharacterMove(el, startOffset); | |
range.collapse(true); | |
if (startOffset == endOffset) { | |
range.move("character", startCharMove); | |
} else { | |
range.moveEnd("character", offsetToRangeCharacterMove(el, endOffset)); | |
range.moveStart("character", startCharMove); | |
} | |
range.select(); | |
} | |
} | |
// http://stackoverflow.com/questions/263743/how-to-get-cursor-position-in-textarea | |
function getCaret(el) { | |
if (el.selectionStart) { | |
return {start: el.selectionStart | |
,end: el.selectionEnd} | |
} else { | |
console.error("No support for selectionStart") | |
} | |
if (document.selection) { | |
el.focus(); | |
var r = document.selection.createRange(); | |
if (r == null) { | |
return 0; | |
} | |
var re = el.createTextRange(), | |
rc = re.duplicate(); | |
re.moveToBookmark(r.getBookmark()); | |
rc.setEndPoint('EndToStart', re); | |
return rc.text.length; | |
} | |
return 0; | |
} | |
// http://snipplr.com/view.php?codeview&id=5144 | |
function setCaret(ctrl, pos) | |
{ | |
if(ctrl.setSelectionRange) | |
{ | |
ctrl.focus(); | |
ctrl.setSelectionRange(pos,pos); | |
} | |
else if (ctrl.createTextRange) { | |
var range = ctrl.createTextRange(); | |
range.collapse(true); | |
range.moveEnd('character', pos); | |
range.moveStart('character', pos); | |
range.select(); | |
} | |
} | |
http://stackoverflow.com/questions/1181700/set-cursor-position-on-contenteditable-div | |
var savedRange; | |
function saveSelection() | |
{ | |
if(window.getSelection)//non IE Browsers | |
{ | |
savedRange = window.getSelection().getRangeAt(0); | |
} | |
else if(document.selection)//IE | |
{ | |
savedRange = document.selection.createRange(); | |
} | |
} | |
function restoreSelection() | |
{ | |
document.getElementById("content").focus(); | |
if (savedRange != null) { | |
if (window.getSelection)//non IE and there is already a selection | |
{ | |
var s = window.getSelection(); | |
if (s.rangeCount > 0) | |
s.removeAllRanges(); | |
s.addRange(savedRange); | |
} | |
else | |
if (document.createRange)//non IE and no selection | |
{ | |
window.getSelection().addRange(savedRange); | |
} | |
else | |
if (document.selection)//IE | |
{ | |
savedRange.select(); | |
} | |
} | |
} | |
</script> | |
</head> | |
<body> | |
<!-- <textarea></textarea> --> | |
<div>Go ahead, and change the text below.</div> | |
<div>Real-time fogja látni mindenki, akinek még meg van nyitva e oldal, hogy mit hogyan szerkesztesz.</div> | |
<div>But be warned: amikor más szerkeszti rajtad kívül, a te kurzorod ide-oda fog ugrálni.</div> | |
<br> | |
<div><input id="name" placeholder="Nevedet írd ide!"> <span>Legutoljára frissítette: </span><span id="info">Töltés...</span></div> | |
<br> | |
<div id="content" contentEditable>Töltés...</div> | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var express = require('express') | |
, io = require('socket.io') | |
app = express.createServer() | |
app.configure(function() { | |
app.use(express.static(__dirname + "/www")) | |
}) | |
app.listen(3000) | |
text = "Alapértelmezett szöveg. Change me!" | |
updatedAt = new Date() | |
updater = "Default_Set_By_Server" | |
// socket.io | |
var socket = io.listen(app); | |
socket.on('connection', function(client){ | |
// new client is here! | |
client.send({m:text, t:updatedAt.toJSON(), u:updater}) | |
client.on('message', function(m){ | |
console.log(m) | |
var out = {} | |
out.m = global.text = m.m | |
out.t = global.updatedAt = new Date() | |
out.u = global.updater = m.u || "Didn't_Give_His_Name" | |
clients = Object.keys(socket.clients) | |
for (var i = clients.length - 1; i >= 0; i--) { | |
if (client.sessionId != clients[i]) { | |
socket.clients[clients[i]].send(out) | |
} | |
} | |
}) | |
client.on('disconnect', function(){ console.log(arguments) }) | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment