Merge pull request #15 from xwiki-labs/diffdom
merge diffdom into netflux
This commit is contained in:
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…
x
Reference in New Issue
Block a user