Skip to content

Instantly share code, notes, and snippets.

@Wizek
Created April 7, 2011 22:05
Show Gist options
  • Save Wizek/908859 to your computer and use it in GitHub Desktop.
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
<!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>
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