Merge pull request #15 from xwiki-labs/diffdom

merge diffdom into netflux
pull/1/head
ansuz 9 years ago
commit 7782069dbd

@ -28,13 +28,16 @@ define([
toolbar;
var module = window.REALTIME_MODULE = {
localChangeInProgress: 0
localChangeInProgress: 0,
Hyperjson: Hyperjson,
Hyperscript: Hyperscript
};
var isNotMagicLine = function (el) {
// factor as:
// return !(el.tagName === 'SPAN' && el.contentEditable === 'false');
var filter = (el.tagName === 'SPAN' && el.contentEditable === 'false');
var filter = (el.tagName === 'SPAN' &&
el.getAttribute('contentEditable') === 'false');
if (filter) {
console.log("[hyperjson.serializer] prevented an element" +
"from being serialized:", el);
@ -95,7 +98,7 @@ define([
we should check when such an element is going to be
removed, and prevent that from happening. */
if (info.node && info.node.tagName === 'SPAN' &&
info.node.contentEditable === "true") {
info.node.getAttribute('contentEditable') === "false") {
// it seems to be a magicline plugin element...
if (info.diff.action === 'removeElement') {
// and you're about to remove it...
@ -163,7 +166,8 @@ define([
doc: inner,
// provide initialstate...
initialState: JSON.stringify(Hyperjson.fromDOM(inner, isNotMagicLine)),
initialState: JSON.stringify(Hyperjson
.fromDOM(inner, isNotMagicLine)) || '{}',
// really basic operational transform
// reject patch if it results in invalid JSON
@ -186,8 +190,7 @@ define([
var localWorkInProgress = function (stage) {
if (module.localChangeInProgress) {
console.error("Applied a change while a local patch was in progress");
alert("local work was interrupted at stage: " + stage);
//module.realtimeInput.onLocal();
console.error("local work was interrupted at stage: " + stage);
return true;
}
return false;
@ -200,6 +203,21 @@ define([
var userDocStateDom = hjsonToDom(JSON.parse(shjson));
localWorkInProgress(2); // check again
/* in the DOM contentEditable is "false"
while "contenteditable" is undefined.
When it goes over the wire, it seems hyperjson transforms it.
of course, hyperjson simply gets attributes from the DOM.
el.attributes returns 'contenteditable', so we have to correct for that
There are quite possibly all sorts of other attributes which might lose
information, and we won't know what they are until after we've lost them.
this comes from hyperscript line 101. FIXME maybe
*/
userDocStateDom.setAttribute("contenteditable", "true"); // lol wtf
localWorkInProgress(3); // check again
var patch = (DD).diff(inner, userDocStateDom);

@ -147,7 +147,8 @@ define([
passwd, // password, to be deprecated (maybe)
channel, // the channel we're to connect to
// initialState argument. (optional)
/* optional unless your application expects JSON
from getUserDoc */
config.initialState || '',
// transform function (optional), which handles conflicts
@ -160,7 +161,6 @@ define([
// this is a problem
warn("realtime.getUserDoc() !== newText");
}
//try{throw new Error();}catch(e){console.log(e.stack);}
};
// pass your shiny new realtime into initialization functions

@ -220,10 +220,9 @@ var transform = Patch.transform = function (origToTransform, transformBy, doc, t
Common.assert(origToTransform.parentHash === transformBy.parentHash);
var resultOfTransformBy = apply(transformBy, doc);
toTransform = clone(origToTransform);
var toTransform = clone(origToTransform);
var text = doc;
for (var i = toTransform.operations.length-1; i >= 0; i--) {
text = Operation.apply(toTransform.operations[i], text);
for (var j = transformBy.operations.length-1; j >= 0; j--) {
toTransform.operations[i] = Operation.transform(text,
toTransform.operations[i],

@ -1,5 +1,4 @@
define([], function () {
// this makes recursing a lot simpler
var isArray = function (A) {
return Object.prototype.toString.call(A)==='[object Array]';
@ -39,8 +38,14 @@ define([], function () {
return cb(hj[0], hj[1], children);
};
var prependDot = function (token) {
return '.' + token;
var classify = function (token) {
return '.' + token.trim();
};
var isValidClass = function (x) {
if (x && /\S/.test(x)) {
return true;
}
};
var isTruthy = function (x) {
@ -61,13 +66,13 @@ define([], function () {
if(!el.attributes){
return;
}
if (predicate) {
if (!predicate(el)) {
// shortcircuit
return;
}
}
var attributes = {};
var i = 0;
@ -91,19 +96,25 @@ define([], function () {
var sel = el.tagName;
if(attributes.id){
// we don't have to do much to validate IDs because the browser
// will only permit one id to exist
// unless we come across a strange browser in the wild
sel = sel +'#'+ attributes.id;
delete attributes.id;
}
if(attributes.class){
// actually parse out classes so that we produce a valid selector
// string. leading or trailing spaces would have caused it to choke
// these are really common in generated html
/* TODO this can be done with RegExps alone, and it will be faster
but this works and is a little less error prone, albeit slower
come back and speed it up when it comes time to optimize */
sel = sel + attributes.class
.split(/\s+/)
.filter(isTruthy)
.map(prependDot)
.join('');
.split(/\s+/g)
.filter(isValidClass)
.map(classify)
.join('')
.replace(/\.\./g, '.');
delete attributes.class;
}
result.push(sel);
@ -116,11 +127,9 @@ define([], function () {
// js hint complains if we use 'var' here
i = 0;
for(; i < el.childNodes.length; i++){
children.push(DOM2HyperJSON(el.childNodes[i], predicate, filter));
}
result.push(children.filter(isTruthy));
if (filter) {

@ -6,6 +6,11 @@ define([
var validate = JsonOT.validate = function (text, toTransform, transformBy) {
try {
// text = O (mutual common ancestor)
// toTransform = A (the first incoming operation)
// transformBy = B (the second incoming operation)
// threeway merge (0, A, B)
var resultOp = ChainPad.Operation.transform0(text, toTransform, transformBy);
var text2 = ChainPad.Operation.apply(transformBy, text);
var text3 = ChainPad.Operation.apply(resultOp, text2);

Loading…
Cancel
Save