Merge branch 'diffdom' into netflux
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user