Merge branch 'diffdom' into netflux

pull/1/head
Yann Flory 9 years ago
commit e207d8b579

@ -45,6 +45,16 @@ define([
return true; return true;
}; };
/* catch `type="_moz"` before it goes over the wire */
var brFilter = function (hj) {
if (hj[1].type === '_moz') { hj[1].type = undefined; }
return hj;
};
var stringifyDOM = function (dom) {
return JSON.stringify(Hyperjson.fromDOM(dom, isNotMagicLine, brFilter));
};
var andThen = function (Ckeditor) { var andThen = function (Ckeditor) {
$(window).on('hashchange', function() { $(window).on('hashchange', function() {
window.location.reload(); window.location.reload();
@ -76,6 +86,8 @@ define([
var inner = window.inner = documentBody; var inner = window.inner = documentBody;
var cursor = window.cursor = Cursor(inner); var cursor = window.cursor = Cursor(inner);
var setEditable = function (bool) { var setEditable = function (bool) {
// careful about putting attributes onto the DOM // careful about putting attributes onto the DOM
// they get put into the chain, and you can have trouble // they get put into the chain, and you can have trouble
@ -165,8 +177,7 @@ define([
doc: inner, doc: inner,
// provide initialstate... // provide initialstate...
initialState: JSON.stringify(Hyperjson initialState: stringifyDOM(inner) || '{}',
.fromDOM(inner, isNotMagicLine)) || '{}',
// really basic operational transform // really basic operational transform
// reject patch if it results in invalid JSON // reject patch if it results in invalid JSON
@ -221,7 +232,8 @@ define([
// build a dom from HJSON, diff, and patch the editor // build a dom from HJSON, diff, and patch the editor
applyHjson(shjson); applyHjson(shjson);
var shjson2 = JSON.stringify(Hyperjson.fromDOM(inner)); var shjson2 = stringifyDOM(inner);
if (shjson2 !== shjson) { if (shjson2 !== shjson) {
console.error("shjson2 !== shjson"); console.error("shjson2 !== shjson");
module.realtimeInput.patchText(shjson2); module.realtimeInput.patchText(shjson2);
@ -255,11 +267,6 @@ define([
var rti = module.realtimeInput = realtimeInput.start(realtimeOptions); var rti = module.realtimeInput = realtimeInput.start(realtimeOptions);
/* catch `type="_moz"` before it goes over the wire */
var brFilter = function (hj) {
if (hj[1].type === '_moz') { hj[1].type = undefined; }
return hj;
};
/* It's incredibly important that you assign 'rti.onLocal' /* It's incredibly important that you assign 'rti.onLocal'
It's used inside of realtimeInput to make sure that all changes It's used inside of realtimeInput to make sure that all changes
@ -270,7 +277,7 @@ define([
the code less extensible. the code less extensible.
*/ */
var propogate = rti.onLocal = function () { var propogate = rti.onLocal = function () {
var shjson = JSON.stringify(Hyperjson.fromDOM(inner, isNotMagicLine, brFilter)); var shjson = stringifyDOM(inner);
if (!rti.patchText(shjson)) { if (!rti.patchText(shjson)) {
return; return;
} }

@ -264,7 +264,8 @@ define([
}, 200); }, 200);
toReturn.patchText = TextPatcher.create({ toReturn.patchText = TextPatcher.create({
realtime: realtime realtime: realtime,
logging: true
}); });
realtime.start(); realtime.start();

@ -23,8 +23,8 @@ var diff = function (oldval, newval) {
commonEnd++; commonEnd++;
} }
var toRemove; var toRemove = 0;
var toInsert; var toInsert = '';
/* throw some assertions in here before dropping patches into the realtime */ /* throw some assertions in here before dropping patches into the realtime */
if (oldval.length !== commonStart + commonEnd) { if (oldval.length !== commonStart + commonEnd) {
@ -79,14 +79,15 @@ var log = function (text, op) {
Due to its reliance on patch, applyChange has side effects on the supplied Due to its reliance on patch, applyChange has side effects on the supplied
realtime facade. realtime facade.
*/ */
var applyChange = function(ctx, oldval, newval) { var applyChange = function(ctx, oldval, newval, logging) {
var op = diff(oldval, newval); var op = diff(oldval, newval);
// log(oldval, op) if (logging) { log(oldval, op) }
patch(ctx, op); patch(ctx, op);
}; };
var create = function(config) { var create = function(config) {
var ctx = config.realtime; var ctx = config.realtime;
var logging = config.logging;
// initial state will always fail the !== check in genop. // initial state will always fail the !== check in genop.
// because nothing will equal this object // because nothing will equal this object
@ -100,7 +101,7 @@ var create = function(config) {
// propogate() // propogate()
return function (newContent) { return function (newContent) {
if (newContent !== content) { if (newContent !== content) {
applyChange(ctx, ctx.getUserDoc(), newContent); applyChange(ctx, ctx.getUserDoc(), newContent, logging);
if (ctx.getUserDoc() !== newContent) { if (ctx.getUserDoc() !== newContent) {
console.log("Expected that: `ctx.getUserDoc() === newContent`!"); console.log("Expected that: `ctx.getUserDoc() === newContent`!");
} }

@ -368,7 +368,7 @@ var random = Patch.random = function (doc, opCount) {
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
var PARANOIA = module.exports.PARANOIA = false; var PARANOIA = module.exports.PARANOIA = true;
/* throw errors over non-compliant messages which would otherwise be treated as invalid */ /* throw errors over non-compliant messages which would otherwise be treated as invalid */
var TESTING = module.exports.TESTING = true; var TESTING = module.exports.TESTING = true;
@ -832,7 +832,7 @@ var check = ChainPad.check = function(realtime) {
Common.assert(uiDoc === realtime.userInterfaceContent); Common.assert(uiDoc === realtime.userInterfaceContent);
} }
var doc = realtime.authDoc; /*var doc = realtime.authDoc;
var patchMsg = realtime.best; var patchMsg = realtime.best;
Common.assert(patchMsg.content.inverseOf.parentHash === realtime.uncommitted.parentHash); Common.assert(patchMsg.content.inverseOf.parentHash === realtime.uncommitted.parentHash);
var patches = []; var patches = [];
@ -844,7 +844,7 @@ var check = ChainPad.check = function(realtime) {
while ((patchMsg = patches.pop())) { while ((patchMsg = patches.pop())) {
doc = Patch.apply(patchMsg.content, doc); doc = Patch.apply(patchMsg.content, doc);
} }
Common.assert(doc === realtime.authDoc); Common.assert(doc === realtime.authDoc);*/
}; };
var doOperation = ChainPad.doOperation = function (realtime, op) { var doOperation = ChainPad.doOperation = function (realtime, op) {

@ -12,8 +12,14 @@
box-sizing: border-box; box-sizing: border-box;
} }
textarea{ textarea{
position: absolute;
top: 5vh;
left: 0px;
border: 0px;
padding-top: 15px;
width: 100%; width: 100%;
height: 100vh; height: 95vh;
max-width: 100%; max-width: 100%;
max-height: 100vh; max-height: 100vh;
@ -32,26 +38,41 @@
color: #637476; color: #637476;
} }
#run { #panel {
position: fixed; position: fixed;
top: 0px; top: 0px;
right: 0px; right: 0px;
width: 100%;
z-index: 100;
width: 5vw;
height: 5vh; height: 5vh;
z-index: 95;
background-color: #777;
/* min-height: 75px; */
}
#run {
display: block;
float: right;
height: 100%;
width: 10vw;
z-index: 100;
line-height: 5vw;
font-size: 1.5em;
background-color: #222; background-color: #222;
color: #CCC; color: #CCC;
display: block;
text-align: center; text-align: center;
border-radius: 5%;
border: 0px;
} }
</style> </style>
</head> </head>
<body> <body>
<textarea></textarea> <textarea></textarea>
<a href="#" id="run">RUN</a> <div id="panel">
<!-- TODO update this element when new users join -->
<span id="users"></span>
<!-- what else should go in the panel? -->
<a href="#" id="run">RUN</a>
</div>
</body> </body>
</html> </html>

@ -3,9 +3,10 @@ define([
'/common/realtime-input.js', '/common/realtime-input.js',
'/common/messages.js', '/common/messages.js',
'/common/crypto.js', '/common/crypto.js',
'/common/cursor.js',
'/bower_components/jquery/dist/jquery.min.js', '/bower_components/jquery/dist/jquery.min.js',
'/customize/pad.js' '/customize/pad.js'
], function (Config, Realtime, Messages, Crypto) { ], function (Config, Realtime, Messages, Crypto, Cursor) {
var $ = window.jQuery; var $ = window.jQuery;
$(window).on('hashchange', function() { $(window).on('hashchange', function() {
window.location.reload(); window.location.reload();
@ -58,7 +59,75 @@ define([
window.alert("Server Connection Lost"); window.alert("Server Connection Lost");
}; };
var rt = Realtime.start(config); var rt = window.rt = Realtime.start(config);
var cursor = Cursor($textarea[0]);
var splice = function (str, index, chars) {
var count = chars.length;
return str.slice(0, index) + chars + str.slice((index -1) + count);
};
var setSelectionRange = function (input, start, end) {
if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(start, end);
} else if (input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', start);
range.select();
}
};
var setCursor = function (el, pos) {
setSelectionRange(el, pos, pos);
};
var state = {};
// TODO
$textarea.on('keydown', function (e) {
// track when control keys are pushed down
//switch (e.key) { }
});
// TODO
$textarea.on('keyup', function (e) {
// track when control keys are released
});
$textarea.on('keypress', function (e) {
switch (e.key) {
case 'Tab':
// insert a tab wherever the cursor is...
var start = $textarea.prop('selectionStart');
var end = $textarea.prop('selectionEnd');
if (typeof start !== 'undefined') {
if (start === end) {
$textarea.val(function (i, val) {
return splice(val, start, "\t");
});
setCursor($textarea[0], start +1);
} else {
// indentation?? this ought to be fun.
}
}
// simulate a keypress so the event goes through..
// prevent default behaviour for tab
e.preventDefault();
rt.bumpSharejs();
break;
default:
break;
}
});
$textarea.on('change', function () {
rt.bumpSharejs();
});
$run.click(function (e) { $run.click(function (e) {
e.preventDefault(); e.preventDefault();

Loading…
Cancel
Save