tests run fine. but it needs some more user testing

This commit is contained in:
Kevin Jahns 2014-10-02 21:14:37 +02:00
parent 968e07a8ff
commit 3415d0ee5e
56 changed files with 1329 additions and 457 deletions

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
!function n(e,t,r){function o(u,s){if(!t[u]){if(!e[u]){var c="function"==typeof require&&require;if(!s&&c)return c(u,!0);if(i)return i(u,!0);throw new Error("Cannot find module '"+u+"'")}var a=t[u]={exports:{}};e[u][0].call(a.exports,function(n){var t=e[u][1][n];return o(t?t:n)},a,a.exports,n,e,t,r)}return t[u].exports}for(var i="function"==typeof require&&require,u=0;u<r.length;u++)o(r[u]);return o}({1:[function(n,e){var t;t=function(){var n,e,t;return t=null,2===arguments.length?(t=new Peer(arguments[0]),e=arguments[1]):(t=new Peer(arguments[0],arguments[1]),t.on("error",function(n){throw new Error("Peerjs connector: "+n)}),t.on("disconnected",function(){throw new Error("Peerjs connector disconnected from signalling server. Cannot accept new connections. Not fatal, but not so good either..")}),e=arguments[2]),n=function(){function n(n,e,r,o){var i,u;this.engine=n,this.HB=e,this.execution_listener=r,this.yatta=o,this.peer=t,this.connections={},this.peer.on("connection",function(n){return function(e){return n.addConnection(e)}}(this)),u=function(n){return function(){var e,t,r,o;r=n.connections,o=[];for(t in r)e=r[t],o.push(e.send({sync_state_vector:n.HB.getOperationCounter()}));return o}}(this),setInterval(u,4e3),i=function(n){return function(e){var t,r,o,i;if(e.uid.creator===n.HB.getUserId()&&"string"!=typeof e.uid.op_number){o=n.connections,i=[];for(r in o)t=o[r],i.push(t.send({op:e}));return i}}}(this),this.execution_listener.push(i)}return n.prototype.connectToPeer=function(n){return null==this.connections[n]&&n!==this.yatta.getUserId()?this.addConnection(t.connect(n)):void 0},n.prototype.getAllConnectionIds=function(){var n,e;e=[];for(n in this.connections)e.push(n);return e},n.prototype.addConnection=function(n){var e,t,r;return this.connections[n.peer]=n,t=!1,e=!1,n.on("data",function(r){return function(o){var i,u,s,c,a;if("empty_message"===o);else if(null!=o.HB){if(t=!0,r.engine.applyOpsCheckDouble(o.HB),!o.initialized)return n.send({conns:r.getAllConnectionIds()})}else{if(null!=o.op)return r.engine.applyOp(o.op);if(null!=o.conns){for(c=o.conns,a=[],u=0,s=c.length;s>u;u++)i=c[u],a.push(r.connectToPeer(i));return a}if(null!=o.sync_state_vector)return n.send({HB:r.yatta.getHistoryBuffer()._encode(o.sync_state_vector),initialized:!0});if(null==o.state_vector)throw new Error("Can't parse this operation: "+o);if(!e)return n.send({HB:r.yatta.getHistoryBuffer()._encode(o.state_vector),initialized:!1}),e=!0}}}(this)),r=function(e){return function(){return n.send({state_vector:e.HB.getOperationCounter()}),t?void 0:setTimeout(r,100)}}(this),r()},n}(),t.on("open",function(t){return e(n,t)})},e.exports=t,"undefined"!=typeof window&&null!==window&&(null==window.Y&&(window.Y={}),window.Y.createPeerJsConnector=t)},{}]},{},[1]);
!function n(e,t,r){function o(s,u){if(!t[s]){if(!e[s]){var c="function"==typeof require&&require;if(!u&&c)return c(s,!0);if(i)return i(s,!0);throw new Error("Cannot find module '"+s+"'")}var a=t[s]={exports:{}};e[s][0].call(a.exports,function(n){var t=e[s][1][n];return o(t?t:n)},a,a.exports,n,e,t,r)}return t[s].exports}for(var i="function"==typeof require&&require,s=0;s<r.length;s++)o(r[s]);return o}({1:[function(n,e){var t;t=function(){var n,e,t;return t=null,2===arguments.length?(t=new Peer(arguments[0]),e=arguments[1]):(t=new Peer(arguments[0],arguments[1]),t.on("error",function(n){throw new Error("Peerjs connector: "+n)}),t.on("disconnected",function(){throw new Error("Peerjs connector disconnected from signalling server. Cannot accept new connections. Not fatal, but not so good either..")}),e=arguments[2]),n=function(){function n(n,e,r,o){var i,s;this.engine=n,this.HB=e,this.execution_listener=r,this.yatta=o,this.peer=t,this.connections={},this.new_connection_listeners=[],this.peer.on("connection",function(n){return function(e){return n.addConnection(e)}}(this)),s=function(n){return function(){var e,t,r,o;r=n.connections,o=[];for(t in r)e=r[t],o.push(e.send({sync_state_vector:n.HB.getOperationCounter()}));return o}}(this),setInterval(s,4e3),i=function(n){return function(e){var t,r,o,i;if(e.uid.creator===n.HB.getUserId()&&"string"!=typeof e.uid.op_number){o=n.connections,i=[];for(r in o)t=o[r],i.push(t.send({op:e}));return i}}}(this),this.execution_listener.push(i)}return n.prototype.connectToPeer=function(n){return null==this.connections[n]&&n!==this.yatta.getUserId()?this.addConnection(t.connect(n)):void 0},n.prototype.getAllConnectionIds=function(){var n,e;e=[];for(n in this.connections)e.push(n);return e},n.prototype.onNewConnection=function(n){return this.new_connection_listeners.push(n)},n.prototype.addConnection=function(n){var e,t,r;return this.connections[n.peer]=n,t=!1,e=!1,n.on("data",function(r){return function(o){var i,s,u,c,a;if("empty_message"===o);else if(null!=o.HB){if(t=!0,r.engine.applyOpsCheckDouble(o.HB),!o.initialized)return n.send({conns:r.getAllConnectionIds()}),r.new_connection_listeners.map(function(e){return e(n)})}else{if(null!=o.op)return r.engine.applyOp(o.op);if(null!=o.conns){for(c=o.conns,a=[],s=0,u=c.length;u>s;s++)i=c[s],a.push(r.connectToPeer(i));return a}if(null!=o.sync_state_vector)return n.send({HB:r.yatta.getHistoryBuffer()._encode(o.sync_state_vector),initialized:!0});if(null==o.state_vector)throw new Error("Can't parse this operation: "+o);if(!e)return n.send({HB:r.yatta.getHistoryBuffer()._encode(o.state_vector),initialized:!1}),e=!0}}}(this)),r=function(e){return function(){return n.send({state_vector:e.HB.getOperationCounter()}),t?void 0:setTimeout(r,100)}}(this),r()},n}(),t.on("open",function(t){return e(n,t)})},e.exports=t,"undefined"!=typeof window&&null!==window&&(null==window.Y&&(window.Y={}),window.Y.createPeerJsConnector=t)},{}]},{},[1]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -26,6 +26,7 @@
this.yatta = yatta;
this.peer = peer;
this.connections = {};
this.new_connection_listeners = [];
this.peer.on('connection', (function(_this) {
return function(conn) {
return _this.addConnection(conn);
@ -80,6 +81,10 @@
return _results;
};
PeerJsConnector.prototype.onNewConnection = function(f) {
return this.new_connection_listeners.push(f);
};
PeerJsConnector.prototype.addConnection = function(conn) {
var initialized_him, initialized_me, sendStateVector;
this.connections[conn.peer] = conn;
@ -94,9 +99,12 @@
initialized_me = true;
_this.engine.applyOpsCheckDouble(data.HB);
if (!data.initialized) {
return conn.send({
conn.send({
conns: _this.getAllConnectionIds()
});
return _this.new_connection_listeners.map(function(f) {
return f(conn);
});
}
} else if (data.op != null) {
return _this.engine.applyOp(data.op);

File diff suppressed because one or more lines are too long

View File

@ -218,12 +218,13 @@
Insert.prototype.type = "Insert";
Insert.prototype.applyDelete = function(o) {
var garbagecollect, _ref;
var callLater, garbagecollect, _ref;
if (this.deleted_by == null) {
this.deleted_by = [];
}
callLater = false;
if ((this.parent != null) && !this.isDeleted()) {
this.parent.callEvent("delete", this, o);
callLater = true;
}
if (o != null) {
this.deleted_by.push(o);
@ -233,6 +234,9 @@
garbagecollect = true;
}
Insert.__super__.applyDelete.call(this, garbagecollect);
if (callLater) {
this.parent.callEvent("delete", this, o);
}
if ((_ref = this.next_cl) != null ? _ref.isDeleted() : void 0) {
return this.next_cl.applyDelete();
}

File diff suppressed because one or more lines are too long

View File

@ -47,11 +47,22 @@
};
TextInsert.prototype.applyDelete = function() {
TextInsert.__super__.applyDelete.apply(this, arguments);
if (this.content instanceof types.Operation) {
this.content.applyDelete();
}
this.content = null;
return TextInsert.__super__.applyDelete.apply(this, arguments);
return this.content = null;
};
TextInsert.prototype.execute = function() {
if (!this.validateSavedOperations()) {
return false;
} else {
if (this.content instanceof types.Operation) {
this.content.insert_parent = this;
}
return TextInsert.__super__.execute.call(this);
}
};
TextInsert.prototype.val = function(current_position) {

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
(function() {
var json_types_uninitialized, proxy_token,
var dont_proxy, json_types_uninitialized, proxy_token, _proxy,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
@ -7,27 +7,45 @@
proxy_token = false;
dont_proxy = function(f) {
var e;
proxy_token = true;
try {
f();
} catch (_error) {
e = _error;
proxy_token = false;
throw new Error(e);
}
return proxy_token = false;
};
_proxy = function(f_name, f) {
var old_f;
old_f = this[f_name];
if (old_f != null) {
return this[f_name] = function() {
var args, that, _ref;
if (!proxy_token && !((_ref = this._yatta) != null ? _ref.isDeleted() : void 0)) {
that = this;
args = arguments;
return dont_proxy(function() {
f.apply(that, args);
return old_f.apply(that, args);
});
} else {
return old_f.apply(this, arguments);
}
};
}
};
if (typeof Element !== "undefined" && Element !== null) {
Element.prototype._proxy = function(f_name, f) {
var old_f;
old_f = this[f_name];
if (old_f != null) {
return this[f_name] = function() {
if (!proxy_token) {
proxy_token = true;
old_f.apply(this, arguments);
f.apply(this, arguments);
return proxy_token = false;
} else {
return old_f.apply(this, arguments);
}
};
}
};
Element.prototype._proxy = _proxy;
}
module.exports = function(HB) {
var XmlType, json_types, parser, types;
var TextNodeType, XmlType, json_types, parser, types;
json_types = json_types_uninitialized(HB);
types = json_types.types;
parser = json_types.parser;
@ -35,7 +53,7 @@
__extends(XmlType, _super);
function XmlType(uid, tagname, attributes, elements, xml) {
var attr, element, i, n, word, _i, _j, _len, _ref, _ref1;
var attr, d, element, i, n, word, _i, _j, _len, _ref, _ref1, _ref2;
this.tagname = tagname;
this.xml = xml;
@ -48,12 +66,18 @@
prev = prev.prev_cl
next = prev.next_cl
*/
XmlType.__super__.constructor.call(this);
XmlType.__super__.constructor.call(this, uid);
if (((_ref = this.xml) != null ? _ref._yatta : void 0) != null) {
d = new types.Delete(void 0, this.xml._yatta);
HB.addOperation(d).execute();
this.xml._yatta = null;
}
if ((attributes != null) && (elements != null)) {
this.saveOperation('attributes', attributes);
this.saveOperation('elements', elements);
} else if ((attributes == null) && (elements == null)) {
this.attributes = new types.JsonType();
this.attributes.setMutableDefault('immutable');
HB.addOperation(this.attributes).execute();
this.elements = new types.WordType();
this.elements.parent = this;
@ -63,17 +87,16 @@
}
if (this.xml != null) {
this.tagname = this.xml.tagName;
for (i = _i = 0, _ref = this.xml.attributes.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
for (i = _i = 0, _ref1 = this.xml.attributes.length; 0 <= _ref1 ? _i < _ref1 : _i > _ref1; i = 0 <= _ref1 ? ++_i : --_i) {
attr = xml.attributes[i];
this.attributes.val(attr.name, attr.value);
}
_ref1 = this.xml.childNodes;
for (_j = 0, _len = _ref1.length; _j < _len; _j++) {
n = _ref1[_j];
_ref2 = this.xml.childNodes;
for (_j = 0, _len = _ref2.length; _j < _len; _j++) {
n = _ref2[_j];
if (n.nodeType === n.TEXT_NODE) {
word = new types.WordType();
word = new TextNodeType(void 0, n);
HB.addOperation(word).execute();
word.push(n.textContent);
this.elements.push(word);
} else if (n.nodeType === n.ELEMENT_NODE) {
element = new XmlType(void 0, void 0, void 0, void 0, n);
@ -90,10 +113,14 @@
XmlType.prototype.type = "XmlType";
XmlType.prototype.applyDelete = function() {
this.attributes.applyDelete();
this.elements.applyDelete();
return XmlType.__super__.applyDelete.call(this);
XmlType.prototype.applyDelete = function(op) {
if ((this.insert_parent != null) && !this.insert_parent.isDeleted()) {
return this.insert_parent.applyDelete(op);
} else {
this.attributes.applyDelete();
this.elements.applyDelete();
return XmlType.__super__.applyDelete.apply(this, arguments);
}
};
XmlType.prototype.cleanup = function() {
@ -101,42 +128,156 @@
};
XmlType.prototype.setXmlProxy = function() {
var insertBefore, removeChild, that;
var findNode, insertBefore, removeChild, renewClassList, that;
this.xml._yatta = this;
that = this;
insertBefore = function(insertedNode, adjacentNode) {
var element, next, prev;
next = adjacentNode != null ? adjacentNode._yatta : void 0;
this.elements.on('insert', function(event, op) {
var newNode, right, rightNode;
if (op.creator !== HB.getUserId() && this === that.elements) {
newNode = op.content.val();
right = op.next_cl;
while ((right != null) && right.isDeleted()) {
right = right.next_cl;
}
rightNode = null;
if (right.type !== 'Delimiter') {
rightNode = right.val().val();
}
return dont_proxy(function() {
return that.xml.insertBefore(newNode, rightNode);
});
}
});
this.elements.on('delete', function(event, op) {
var del_op, deleted;
del_op = op.deleted_by[0];
if ((del_op != null) && del_op.creator !== HB.getUserId() && this === that.elements) {
deleted = op.content.val();
return dont_proxy(function() {
return that.xml.removeChild(deleted);
});
}
});
this.attributes.on(['addProperty', 'change'], function(event, property_name, op) {
if (op.creator !== HB.getUserId() && this === that.attributes) {
return dont_proxy(function() {
var newval;
newval = op.val().val();
if (newval != null) {
return that.xml.setAttribute(property_name, op.val().val());
} else {
return that.xml.removeAttribute(property_name);
}
});
}
});
findNode = function(child) {
var elem;
if (child == null) {
throw new Error("you must specify a parameter!");
}
child = child._yatta;
elem = that.elements.beginning.next_cl;
while (elem.type !== 'Delimiter' && elem.content !== child) {
elem = elem.next_cl;
}
if (elem.type === 'Delimiter') {
return false;
} else {
return elem;
}
};
insertBefore = function(insertedNode_s, adjacentNode) {
var child, element, inserted_nodes, next, prev, _results;
next = null;
if (adjacentNode != null) {
next = findNode(adjacentNode);
}
prev = null;
if (next != null) {
if (next) {
prev = next.prev_cl;
} else {
prev = this._yatta.elements.end.prev_cl;
while (prev.isDeleted()) {
prev = prev.prev_cl;
}
}
inserted_nodes = null;
if (insertedNode_s.nodeType === insertedNode_s.DOCUMENT_FRAGMENT_NODE) {
child = insertedNode_s.lastChild;
_results = [];
while (child != null) {
element = new XmlType(void 0, void 0, void 0, void 0, child);
HB.addOperation(element).execute();
that.elements.insertAfter(prev, element);
_results.push(child = child.previousSibling);
}
return _results;
} else {
element = new XmlType(void 0, void 0, void 0, void 0, insertedNode_s);
HB.addOperation(element).execute();
return that.elements.insertAfter(prev, element);
}
element = new XmlType(void 0, void 0, void 0, void 0, insertedNode);
HB.addOperation(element).execute();
return that.elements.insertAfter(prev, element);
};
this.xml._proxy('insertBefore', insertBefore);
this.xml._proxy('appendChild', insertBefore);
this.xml._proxy('removeAttribute', function(name) {
return that.attributes.val(name, void 0);
});
this.xml._proxy('setAttribute', function(name, value) {
return that.attributes.val(name, value);
});
renewClassList = function(newclass) {
var dont_do_it, elem, value, _i, _len;
dont_do_it = false;
if (newclass != null) {
for (_i = 0, _len = this.length; _i < _len; _i++) {
elem = this[_i];
if (newclass === elem) {
dont_do_it = true;
}
}
}
value = Array.prototype.join.call(this, " ");
if ((newclass != null) && !dont_do_it) {
value += " " + newclass;
}
return that.attributes.val('class', value);
};
_proxy.call(this.xml.classList, 'add', renewClassList);
_proxy.call(this.xml.classList, 'remove', renewClassList);
this.xml.__defineSetter__('className', function(val) {
return this.setAttribute('class', val);
});
this.xml.__defineGetter__('className', function() {
return that.attributes.val('class');
});
this.xml.__defineSetter__('textContent', function(val) {
var elem, remove, text_node;
elem = that.xml.firstChild;
while (elem != null) {
remove = elem;
elem = elem.nextSibling;
that.xml.removeChild(remove);
}
if (val !== "") {
text_node = document.createTextNode(val);
return that.xml.appendChild(text_node);
}
});
removeChild = function(node) {
var d, elem;
elem = that.elements.beginning.next_cl;
while (elem.type !== 'Delimiter' && elem.content !== node._yatta) {
elem = elem.next_cl;
}
if (elem.type === 'Delimiter') {
elem = findNode(node);
if (!elem) {
throw new Error("You are only allowed to delete existing (direct) child elements!");
}
d = new types.Delete(void 0, elem);
return HB.addOperation(d).execute();
HB.addOperation(d).execute();
return node._yatta = null;
};
this.xml._proxy('removeChild', removeChild);
return this.xml._proxy('replaceChild', function(insertedNode, replacedNode) {
insertBefore.call(this, replacedNode, insertedNode);
insertBefore.call(this, insertedNode, replacedNode);
return removeChild.call(this, replacedNode);
});
};
@ -161,11 +302,12 @@
e = this.elements.beginning.next_cl;
while (e.type !== "Delimiter") {
n = e.content;
if (!e.isDeleted()) {
if (!e.isDeleted() && (e.content != null)) {
if (n.type === "XmlType") {
this.xml.appendChild(n.val(enforce));
} else if (n.type === "WordType") {
text_node = document.createTextNode(n.val());
} else if (n.type === "TextNodeType") {
text_node = n.val();
text_node._yatta = this;
this.xml.appendChild(text_node);
} else {
throw new Error("Internal structure cannot be transformed to dom");
@ -180,7 +322,7 @@
};
XmlType.prototype.execute = function() {
return XmlType.__super__.execute.apply(this, arguments);
return XmlType.__super__.execute.call(this);
};
@ -216,6 +358,49 @@
uid = json['uid'], attributes = json['attributes'], elements = json['elements'], tagname = json['tagname'];
return new XmlType(uid, tagname, attributes, elements, void 0);
};
TextNodeType = (function(_super) {
__extends(TextNodeType, _super);
function TextNodeType(uid, content) {
var d;
if (content._yatta != null) {
d = new types.Delete(void 0, content._yatta);
HB.addOperation(d).execute();
content._yatta = null;
}
this._yatta = this;
TextNodeType.__super__.constructor.call(this, uid, content);
}
TextNodeType.prototype.applyDelete = function(op) {
if ((this.insert_parent != null) && !this.insert_parent.isDeleted()) {
return this.insert_parent.applyDelete(op);
} else {
return TextNodeType.__super__.applyDelete.apply(this, arguments);
}
};
TextNodeType.prototype.type = "TextNodeType";
TextNodeType.prototype._encode = function() {
var json;
json = {
'type': this.type,
'uid': this.getUid(),
'content': this.content.textContent
};
return json;
};
return TextNodeType;
})(types.ImmutableObject);
parser['TextNodeType'] = function(json) {
var content, textnode, uid;
uid = json['uid'], content = json['content'];
textnode = document.createTextNode(content);
return new TextNodeType(uid, textnode);
};
types['XmlType'] = XmlType;
return json_types;
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -100,11 +100,6 @@
XmlFramework
</a>
</li>
<li>
<a href='class/XmlType.html'>
XmlType
</a>
</li>
</ul>
</ul>
</div>
@ -257,21 +252,13 @@
(lib&#47;Frameworks)
</small>
</li>
<li>
<a href='file/lib/Types/XmlTypes.coffee.html'>
XmlTypes.coffee
</a>
<small>
(lib&#47;Types)
</small>
</li>
</ul>
</ul>
</div>
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -302,7 +302,7 @@ data from the received intent.</p>
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -335,7 +335,7 @@ JsonFramework was initialized (Depending on the HistoryBuffer implementation).</
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -466,7 +466,7 @@ if (x.type === &quot;JsonType&quot;) {
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -139,7 +139,7 @@ console.log(w.newProperty == &quot;Awesome&quot;) # true!</code></pre>
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -72,6 +72,17 @@ user-id of the peer (browser/client). And then you can connect to it.</p>
Receive the id of every connected peer.
</span>
</li>
<li>
<span class='signature'>
<a href='#onNewConnection-dynamic'>
#
(void)
<b>onNewConnection</b><span>(f)</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#addConnection-dynamic'>
@ -194,6 +205,15 @@ on how to do that with urls.</p>
</li>
</ul>
</div>
</div>
<div class='method_details'>
<p class='signature' id='onNewConnection-dynamic'>
#
(void)
<b>onNewConnection</b><span>(f)</span>
<br>
</p>
</div>
<div class='method_details'>
<p class='signature' id='addConnection-dynamic'>
@ -222,7 +242,7 @@ on how to do that with urls.</p>
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -356,7 +356,7 @@ JsonFramework was initialized (Depending on the HistoryBuffer implementation).</
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -455,7 +455,7 @@ yatta.bind(textbox);</code></pre>
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -44,8 +44,9 @@
<p>Manages XML types
Not supported:</p><ul>
<li>Attribute nodes</li>
<li>Real replace of child elements (to much overhead). Currently, the new element is inserted after the &#39;replaced&#39; element, and then it is deleted.
*</li>
<li>Real replace of child elements (to much overhead). Currently, the new element is inserted after the &#39;replaced&#39; element, and then it is deleted.</li>
<li>Namespaces (*NS)</li>
<li>Browser specific methods (webkit-* operations)</li>
</ul>
</div>
@ -122,7 +123,6 @@ Use it in order to check whether this is an xml-type or something else.</p>
</a>
</span>
<span class='desc'>
If possible set the replace manager in the content.
</span>
</li>
<li>
@ -208,17 +208,7 @@ Use it in order to check whether this is an xml-type or something else.</p>
<b>execute</b><span>()</span>
<br>
</p>
<div class='docstring'>
<p>If possible set the replace manager in the content.</p>
</div>
<div class='tags'>
<h3>See also:</h3>
<ul class='see'>
<li>
<a href='WordType.setReplaceManager'>WordType.setReplaceManager</a>
</li>
</ul>
</div>
</div>
<div class='method_details'>
<p class='signature' id='getParent-dynamic'>
@ -258,7 +248,7 @@ This result can be send to other clients.</p>
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 15:16:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -99,18 +99,6 @@
</small>
<small class='namespace'>
</small>
</li>
<li>
<a href='class/XmlType.html' target='main'>
XmlType
</a>
<small class='parent'>
<
types.Insert
</small>
<small class='namespace'>
</small>
</li>
</ul>

View File

@ -38,7 +38,7 @@
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -70,7 +70,7 @@ But I would become really motivated if you gave me some feedback :) (<a href="ht
<ul>
<li>XML support</li>
</ul>
<h2 id="support">Support</h2><p>Please report any issues to the <a href="https://github.com/DadaMonad/Yatta/issues">Github issue page</a>!</p><h2 id="license">License</h2><p>Yatta! is licensed under the <a href="./LICENSE.txt">MIT License</a>.</p><a href="&#x6d;&#97;&#x69;&#x6c;&#x74;&#111;&#58;&#x6b;&#101;&#x76;&#x69;&#110;&#46;&#x6a;&#x61;&#104;&#x6e;&#x73;&#64;&#x72;&#119;&#x74;&#104;&#45;&#97;&#97;&#x63;&#104;&#x65;&#x6e;&#x2e;&#100;&#x65;">&#x6b;&#101;&#x76;&#x69;&#110;&#46;&#x6a;&#x61;&#104;&#x6e;&#x73;&#64;&#x72;&#119;&#x74;&#104;&#45;&#97;&#97;&#x63;&#104;&#x65;&#x6e;&#x2e;&#100;&#x65;</a>
<h2 id="support">Support</h2><p>Please report any issues to the <a href="https://github.com/DadaMonad/Yatta/issues">Github issue page</a>!</p><h2 id="license">License</h2><p>Yatta! is licensed under the <a href="./LICENSE.txt">MIT License</a>.</p><a href="&#x6d;&#97;&#105;&#108;&#116;&#111;&#58;&#x6b;&#x65;&#118;&#105;&#x6e;&#x2e;&#106;&#x61;&#104;&#x6e;&#115;&#x40;&#114;&#x77;&#x74;&#x68;&#45;&#97;&#97;&#99;&#x68;&#x65;&#110;&#x2e;&#100;&#x65;">&#x6b;&#x65;&#118;&#105;&#x6e;&#x2e;&#106;&#x61;&#104;&#x6e;&#115;&#x40;&#114;&#x77;&#x74;&#x68;&#45;&#97;&#97;&#99;&#x68;&#x65;&#110;&#x2e;&#100;&#x65;</a>
@ -79,7 +79,7 @@ But I would become really motivated if you gave me some feedback :) (<a href="ht
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -100,7 +100,7 @@
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -158,7 +158,7 @@
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -39,7 +39,7 @@
</table>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -48,7 +48,7 @@
</dl>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -60,7 +60,7 @@
</dl>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -60,7 +60,7 @@
</dl>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -48,7 +48,7 @@
</dl>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -39,7 +39,7 @@
</table>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -39,7 +39,7 @@
</table>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -39,7 +39,7 @@
</table>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -39,7 +39,7 @@
</table>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -53,15 +53,34 @@ But yatta&#39;s proxy may be called only once!</p>
<div class='tags'>
</div>
</dd>
<dt id='Element.prototype._proxy-variable'>
Element.prototype._proxy
=
</dt>
<dd>
<pre><code class='coffeescript'>_proxy</code></pre>
</dd>
</dl>
<h2>Method Summary</h2>
<ul class='summary'>
<li>
<span class='signature'>
<a href='#Element-'>
<a href='#dont_proxy-'>
~
(void)
<b>Element</b><span>(f_name, f)</span>
<b>dont_proxy</b><span>(f)</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#_proxy-'>
~
(void)
<b>_proxy</b><span>(f_name, f)</span>
</a>
</span>
<span class='desc'>
@ -71,10 +90,19 @@ But yatta&#39;s proxy may be called only once!</p>
<h2>Method Details</h2>
<div class='methods'>
<div class='method_details'>
<p class='signature' id='Element-'>
<p class='signature' id='dont_proxy-'>
~
(void)
<b>Element</b><span>(f_name, f)</span>
<b>dont_proxy</b><span>(f)</span>
<br>
</p>
</div>
<div class='method_details'>
<p class='signature' id='_proxy-'>
~
(void)
<b>_proxy</b><span>(f_name, f)</span>
<br>
</p>
@ -82,7 +110,7 @@ But yatta&#39;s proxy may be called only once!</p>
</div>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 15:16:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -37,7 +37,7 @@
</table>
</div>
<div id='footer'>
September 29, 14 16:10:05 by
October 02, 14 21:00:56 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -153,14 +153,6 @@
lib&#47;Types
</small>
</li>
<li>
<a href='file/lib/Types/XmlTypes.coffee.html' target='main'>
XmlTypes.coffee
</a>
<small class='namespace'>
lib&#47;Types
</small>
</li>
</ul>
<li>

File diff suppressed because one or more lines are too long

View File

@ -30,19 +30,11 @@
</div>
<ul>
<li>
<a href='file/lib/Types/XmlTypes.coffee.html#Element-' target='main' title='Element'>
~Element
</a>
<small>
(lib&#47;Types&#47;XmlTypes.coffee)
</small>
</li>
<li>
<a href='class/XmlType.html#_encode-dynamic' target='main' title='_encode'>
<a href='class/WordType.html#_encode-dynamic' target='main' title='_encode'>
#_encode
</a>
<small>
(XmlType)
(WordType)
</small>
</li>
<li>
@ -53,14 +45,6 @@
(JsonType)
</small>
</li>
<li>
<a href='class/WordType.html#_encode-dynamic' target='main' title='_encode'>
#_encode
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/PeerJsConnector.html#addConnection-dynamic' target='main' title='addConnection'>
#addConnection
@ -69,6 +53,14 @@
(PeerJsConnector)
</small>
</li>
<li>
<a href='class/WordType.html#applyDelete-dynamic' target='main' title='applyDelete'>
#applyDelete
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/JsonType.html#applyDelete-dynamic' target='main' title='applyDelete'>
#applyDelete
@ -78,16 +70,8 @@
</small>
</li>
<li>
<a href='class/XmlType.html#applyDelete-dynamic' target='main' title='applyDelete'>
#applyDelete
</a>
<small>
(XmlType)
</small>
</li>
<li>
<a href='class/WordType.html#applyDelete-dynamic' target='main' title='applyDelete'>
#applyDelete
<a href='class/WordType.html#bind-dynamic' target='main' title='bind'>
#bind
</a>
<small>
(WordType)
@ -102,8 +86,8 @@
</small>
</li>
<li>
<a href='class/WordType.html#bind-dynamic' target='main' title='bind'>
#bind
<a href='class/WordType.html#cleanup-dynamic' target='main' title='cleanup'>
#cleanup
</a>
<small>
(WordType)
@ -117,22 +101,6 @@
(JsonType)
</small>
</li>
<li>
<a href='class/WordType.html#cleanup-dynamic' target='main' title='cleanup'>
#cleanup
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/XmlType.html#cleanup-dynamic' target='main' title='cleanup'>
#cleanup
</a>
<small>
(XmlType)
</small>
</li>
<li>
<a href='class/PeerJsConnector.html#connectToPeer-dynamic' target='main' title='connectToPeer'>
#connectToPeer
@ -141,30 +109,6 @@
(PeerJsConnector)
</small>
</li>
<li>
<a href='class/WordType.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/XmlType.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(XmlType)
</small>
</li>
<li>
<a href='class/PeerJsConnector.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(PeerJsConnector)
</small>
</li>
<li>
<a href='class/IwcConnector.html#constructor-dynamic' target='main' title='constructor'>
#constructor
@ -173,6 +117,22 @@
(IwcConnector)
</small>
</li>
<li>
<a href='class/JsonFramework.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(JsonFramework)
</small>
</li>
<li>
<a href='class/PeerJsConnector.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(PeerJsConnector)
</small>
</li>
<li>
<a href='class/JsonType.html#constructor-dynamic' target='main' title='constructor'>
#constructor
@ -197,6 +157,14 @@
(XmlFramework)
</small>
</li>
<li>
<a href='class/WordType.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/TextFramework.html#constructor-dynamic' target='main' title='constructor'>
#constructor
@ -205,14 +173,6 @@
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(JsonFramework)
</small>
</li>
<li>
<a href='file/lib/Connectors/IwcConnector.coffee.html#createIwcConnector-' target='main' title='createIwcConnector'>
~createIwcConnector
@ -253,14 +213,6 @@
(TextFramework)
</small>
</li>
<li>
<a href='class/XmlType.html#execute-dynamic' target='main' title='execute'>
#execute
</a>
<small>
(XmlType)
</small>
</li>
<li>
<a href='class/PeerJsConnector.html#getAllConnectionIds-dynamic' target='main' title='getAllConnectionIds'>
#getAllConnectionIds
@ -269,14 +221,6 @@
(PeerJsConnector)
</small>
</li>
<li>
<a href='class/TextFramework.html#getConnector-dynamic' target='main' title='getConnector'>
#getConnector
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#getConnector-dynamic' target='main' title='getConnector'>
#getConnector
@ -285,6 +229,14 @@
(JsonFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#getConnector-dynamic' target='main' title='getConnector'>
#getConnector
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#getConnector-dynamic' target='main' title='getConnector'>
#getConnector
@ -293,6 +245,14 @@
(XmlFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#getHistoryBuffer-dynamic' target='main' title='getHistoryBuffer'>
#getHistoryBuffer
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#getHistoryBuffer-dynamic' target='main' title='getHistoryBuffer'>
#getHistoryBuffer
@ -309,14 +269,6 @@
(JsonFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#getHistoryBuffer-dynamic' target='main' title='getHistoryBuffer'>
#getHistoryBuffer
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonType.html#getParent-dynamic' target='main' title='getParent'>
#getParent
@ -325,14 +277,6 @@
(JsonType)
</small>
</li>
<li>
<a href='class/XmlType.html#getParent-dynamic' target='main' title='getParent'>
#getParent
</a>
<small>
(XmlType)
</small>
</li>
<li>
<a href='class/XmlFramework.html#getSharedObject-dynamic' target='main' title='getSharedObject'>
#getSharedObject
@ -357,14 +301,6 @@
(JsonFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId
@ -373,6 +309,14 @@
(TextFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId
@ -405,14 +349,6 @@
(WordType)
</small>
</li>
<li>
<a href='class/XmlFramework.html#on-dynamic' target='main' title='on'>
#on
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#on-dynamic' target='main' title='on'>
#on
@ -421,6 +357,14 @@
(TextFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#on-dynamic' target='main' title='on'>
#on
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#on-dynamic' target='main' title='on'>
#on
@ -429,6 +373,14 @@
(JsonFramework)
</small>
</li>
<li>
<a href='class/PeerJsConnector.html#onNewConnection-dynamic' target='main' title='onNewConnection'>
#onNewConnection
</a>
<small>
(PeerJsConnector)
</small>
</li>
<li>
<a href='class/WordType.html#push-dynamic' target='main' title='push'>
#push
@ -485,14 +437,6 @@
(IwcConnector)
</small>
</li>
<li>
<a href='class/XmlFramework.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
#setMutableDefault
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
#setMutableDefault
@ -509,6 +453,14 @@
(JsonType)
</small>
</li>
<li>
<a href='class/XmlFramework.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
#setMutableDefault
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/JsonType.html#setReplaceManager-dynamic' target='main' title='setReplaceManager'>
#setReplaceManager
@ -525,14 +477,6 @@
(WordType)
</small>
</li>
<li>
<a href='class/XmlType.html#setXmlProxy-dynamic' target='main' title='setXmlProxy'>
#setXmlProxy
</a>
<small>
(XmlType)
</small>
</li>
<li>
<a href='class/XmlFramework.html#toJson-dynamic' target='main' title='toJson'>
#toJson
@ -565,14 +509,6 @@
(WordType)
</small>
</li>
<li>
<a href='class/TextFramework.html#val-dynamic' target='main' title='val'>
#val
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/WordType.html#val-dynamic' target='main' title='val'>
#val
@ -582,19 +518,19 @@
</small>
</li>
<li>
<a href='class/XmlType.html#val-dynamic' target='main' title='val'>
<a href='class/TextFramework.html#val-dynamic' target='main' title='val'>
#val
</a>
<small>
(XmlType)
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#val-dynamic' target='main' title='val'>
<a href='class/XmlFramework.html#val-dynamic' target='main' title='val'>
#val
</a>
<small>
(JsonFramework)
(XmlFramework)
</small>
</li>
<li>
@ -606,11 +542,11 @@
</small>
</li>
<li>
<a href='class/XmlFramework.html#val-dynamic' target='main' title='val'>
<a href='class/JsonFramework.html#val-dynamic' target='main' title='val'>
#val
</a>
<small>
(XmlFramework)
(JsonFramework)
</small>
</li>
</ul>

View File

@ -194,7 +194,7 @@ Apply a 'change' - listener to a JsonType.
console.log("New value: " + show(this.val(property_name)) + ""); // 'this' is the object on which the property changed.
};
yatta.on('change', change);
yatta.val('mutable_string', "text", 'mutable'); // Property 'mutable_string' was replaced or changed!
yatta.val('mutable_string', "text", 'mutable'); // You changed the value of property 'mutable_string'!
```

View File

@ -156,7 +156,7 @@ Y.createPeerJsConnector("unique_id", {key: 'h7nlefbgavh1tt9'}, function(Connecto
console.log("New value: " + show(this.val(property_name)) + ""); // 'this' is the object on which the property changed.
};
yatta.on('change', change);
yatta.val('mutable_string', "text", 'mutable'); // Property 'mutable_string' was replaced or changed!
yatta.val('mutable_string', "text", 'mutable'); // You changed the value of property 'mutable_string'!
/**
'change' and 'addProperty' do also fire for nested properties.

View File

@ -27,6 +27,41 @@ var yatta, yattaHandler;
Y.createPeerJsConnector({key: 'h7nlefbgavh1tt9'}, function(Connector, user_id){
yatta = new Y.XmlFramework(user_id, Connector);
console.log(yatta.getUserId());
```
Get the url of this frame. If it has a url-encoded parameter
we will connect to the foreign peer.
```js
var url = window.location.href;
var peer_id = location.search
var url = url.substring(0,-peer_id.length);
peer_id = peer_id.substring(1);
```
Set the shareable link.
```js
document.getElementById("peer_link").setAttribute("href",url+"?"+user_id);
```
Connect to other peer.
```js
if (peer_id.length > 0){
yatta.connector.connectToPeer(peer_id);
}
yatta.connector.onNewConnection(function(){
$("#collaborative").replaceWith(yatta.val())
});
yatta.val($("#collaborative")[0])
console.log(yatta.getUserId());
});
```

View File

@ -9,14 +9,17 @@
<script src="./index.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<h1> PeerJs + Json Tutorial</h1>
<p> Collaborative Json editing with <a href="https://github.com/DadaMonad/Yatta/">Yatta</a>
<body id="collaborative">
<h1> PeerJs + XML Example</h1>
<p> Collaborative XML editing with <a href="https://github.com/DadaMonad/Yatta/">Yatta</a>
and <a href="http://peerjs.com/">PeerJs</a> (WebRTC). </p>
<p> <a href="https://github.com/DadaMonad/Yatta/">Yatta</a> is a Framework for Real-Time collaboration on arbitrary data structures.
You can find the code for this example <a href="https://github.com/DadaMonad/Yatta/tree/master/examples/PeerJs-Json">here</a>.
<a id="peer_link" target="_blank">Drop me </a>
</p>
</body>
</html>

View File

@ -27,5 +27,31 @@ var yatta, yattaHandler;
Y.createPeerJsConnector({key: 'h7nlefbgavh1tt9'}, function(Connector, user_id){
yatta = new Y.XmlFramework(user_id, Connector);
console.log(yatta.getUserId());
/**
Get the url of this frame. If it has a url-encoded parameter
we will connect to the foreign peer.
*/
var url = window.location.href;
var peer_id = location.search
var url = url.substring(0,-peer_id.length);
peer_id = peer_id.substring(1);
/**
Set the shareable link.
*/
document.getElementById("peer_link").setAttribute("href",url+"?"+user_id);
/**
Connect to other peer.
*/
if (peer_id.length > 0){
yatta.connector.connectToPeer(peer_id);
}
yatta.connector.onNewConnection(function(){
$("#collaborative").replaceWith(yatta.val())
});
yatta.val($("#collaborative")[0])
console.log(yatta.getUserId());
});

View File

@ -39,6 +39,7 @@ createPeerJsConnector = ()->
@peer = peer
@connections = {}
@new_connection_listeners = []
@peer.on 'connection', (conn)=>
@addConnection conn
@ -82,6 +83,9 @@ createPeerJsConnector = ()->
for conn_id of @connections
conn_id
onNewConnection: (f)->
@new_connection_listeners.push f
#
# Adds an existing connection to this connector.
# @param conn {PeerJsConnection}
@ -105,6 +109,8 @@ createPeerJsConnector = ()->
if not data.initialized
conn.send
conns: @getAllConnectionIds()
@new_connection_listeners.map (f)->
f(conn)
else if data.op?
@engine.applyOp data.op
else if data.conns?

View File

@ -271,15 +271,18 @@ module.exports = (HB)->
#
applyDelete: (o)->
@deleted_by ?= []
callLater = false
if @parent? and not @isDeleted()
# call iff wasn't deleted earlyer
@parent.callEvent "delete", @, o
callLater = true
if o?
@deleted_by.push o
garbagecollect = false
if not (@prev_cl? and @next_cl?) or @prev_cl.isDeleted()
garbagecollect = true
super garbagecollect
if callLater
@parent.callEvent "delete", @, o
if @next_cl?.isDeleted()
# garbage collect next_cl
@next_cl.applyDelete()

View File

@ -43,10 +43,18 @@ module.exports = (HB)->
@content.length
applyDelete: ()->
super # no braces indeed!
if @content instanceof types.Operation
@content.applyDelete()
@content = null
super
execute: ()->
if not @validateSavedOperations()
return false
else
if @content instanceof types.Operation
@content.insert_parent = @
super()
#
# The result will be concatenated with the results from the other insert operations

View File

@ -5,15 +5,25 @@ json_types_uninitialized = require "./JsonTypes"
# For example xml.insertChild(dom) , wich inserts an element at the end, and xml.insertAfter(dom,null) wich does the same
# But yatta's proxy may be called only once!
proxy_token = false
dont_proxy = (f)->
proxy_token = true
try
f()
catch e
proxy_token = false
throw new Error e
proxy_token = false
_proxy = (f_name, f)->
old_f = @[f_name]
if old_f?
@[f_name] = ()->
if not proxy_token and not @_yatta?.isDeleted()
proxy_token = true
old_f.apply this, arguments
f.apply this, arguments
proxy_token = false
that = this
args = arguments
dont_proxy ()->
f.apply that, args
old_f.apply that, args
else
old_f.apply this, arguments
#else
@ -48,11 +58,18 @@ module.exports = (HB)->
super(uid)
if @xml?._yatta?
d = new types.Delete undefined, @xml._yatta
HB.addOperation(d).execute()
@xml._yatta = null
if attributes? and elements?
@saveOperation 'attributes', attributes
@saveOperation 'elements', elements
else if (not attributes?) and (not elements?)
@attributes = new types.JsonType()
@attributes.setMutableDefault 'immutable'
HB.addOperation(@attributes).execute()
@elements = new types.WordType()
@elements.parent = @
@ -67,11 +84,9 @@ module.exports = (HB)->
@attributes.val(attr.name, attr.value)
for n in @xml.childNodes
if n.nodeType is n.TEXT_NODE
word = new types.WordType()
word = new TextNodeType(undefined, n)
HB.addOperation(word).execute()
word.push n.textContent
@elements.push word
n._yatta = word
else if n.nodeType is n.ELEMENT_NODE
element = new XmlType undefined, undefined, undefined, undefined, n
HB.addOperation(element).execute()
@ -87,10 +102,13 @@ module.exports = (HB)->
#
type: "XmlType"
applyDelete: ()->
@attributes.applyDelete()
@elements.applyDelete()
super()
applyDelete: (op)->
if @insert_parent? and not @insert_parent.isDeleted()
@insert_parent.applyDelete op
else
@attributes.applyDelete()
@elements.applyDelete()
super
cleanup: ()->
super()
@ -98,11 +116,50 @@ module.exports = (HB)->
setXmlProxy: ()->
@xml._yatta = @
that = @
@elements.on 'insert', (event, op)->
if op.creator isnt HB.getUserId() and this is that.elements
newNode = op.content.val()
right = op.next_cl
while right? and right.isDeleted()
right = right.next_cl
rightNode = null
if right.type isnt 'Delimiter'
rightNode = right.val().val()
dont_proxy ()->
that.xml.insertBefore newNode, rightNode
@elements.on 'delete', (event, op)->
del_op = op.deleted_by[0]
if del_op? and del_op.creator isnt HB.getUserId() and this is that.elements
deleted = op.content.val()
dont_proxy ()->
that.xml.removeChild deleted
@attributes.on ['addProperty', 'change'], (event, property_name, op)->
if op.creator isnt HB.getUserId() and this is that.attributes
dont_proxy ()->
newval = op.val().val()
if newval?
that.xml.setAttribute(property_name, op.val().val())
else
that.xml.removeAttribute(property_name)
## Here are all methods that proxy the behavior of the xml
# you want to find a specific child element. Since they are carried by an Insert-Type, you want to find that Insert-Operation.
# @param child {DomElement} Dom element.
# @return {InsertType} This carries the XmlType that represents the DomElement (child). false if i couldn't find it.
#
findNode = (child)->
if not child?
throw new Error "you must specify a parameter!"
child = child._yatta
elem = that.elements.beginning.next_cl
while elem.type isnt 'Delimiter' and elem.content isnt child
@ -112,7 +169,7 @@ module.exports = (HB)->
else
elem
insertBefore = (insertedNode, adjacentNode)->
insertBefore = (insertedNode_s, adjacentNode)->
next = null
if adjacentNode?
next = findNode adjacentNode
@ -121,9 +178,21 @@ module.exports = (HB)->
prev = next.prev_cl
else
prev = @_yatta.elements.end.prev_cl
element = new XmlType undefined, undefined, undefined, undefined, insertedNode
HB.addOperation(element).execute()
that.elements.insertAfter prev, element
while prev.isDeleted()
prev = prev.prev_cl
inserted_nodes = null
if insertedNode_s.nodeType is insertedNode_s.DOCUMENT_FRAGMENT_NODE
child = insertedNode_s.lastChild
while child?
element = new XmlType undefined, undefined, undefined, undefined, child
HB.addOperation(element).execute()
that.elements.insertAfter prev, element
child = child.previousSibling
else
element = new XmlType undefined, undefined, undefined, undefined, insertedNode_s
HB.addOperation(element).execute()
that.elements.insertAfter prev, element
@xml._proxy 'insertBefore', insertBefore
@xml._proxy 'appendChild', insertBefore
@xml._proxy 'removeAttribute', (name)->
@ -131,8 +200,16 @@ module.exports = (HB)->
@xml._proxy 'setAttribute', (name, value)->
that.attributes.val name, value
renewClassList = ()->
that.attributes.val('class', Array.prototype.join.call this, " ")
renewClassList = (newclass)->
dont_do_it = false
if newclass?
for elem in this
if newclass is elem
dont_do_it = true
value = Array.prototype.join.call this, " "
if newclass? and not dont_do_it
value += " "+newclass
that.attributes.val('class', value )
_proxy.call @xml.classList, 'add', renewClassList
_proxy.call @xml.classList, 'remove', renewClassList
@xml.__defineSetter__ 'className', (val)->
@ -158,6 +235,7 @@ module.exports = (HB)->
throw new Error "You are only allowed to delete existing (direct) child elements!"
d = new types.Delete undefined, elem
HB.addOperation(d).execute()
node._yatta = null
@xml._proxy 'removeChild', removeChild
@xml._proxy 'replaceChild', (insertedNode, replacedNode)->
insertBefore.call this, insertedNode, replacedNode
@ -180,12 +258,11 @@ module.exports = (HB)->
e = @elements.beginning.next_cl
while e.type isnt "Delimiter"
n = e.content
if not e.isDeleted()
if not e.isDeleted() and e.content? # TODO: how can this happen? Probably because listeners
if n.type is "XmlType"
@xml.appendChild n.val(enforce)
else if n.type is "WordType"
text_node = document.createTextNode n.val()
text_node._yatta = @
else if n.type is "TextNodeType"
text_node = n.val()
@xml.appendChild text_node
else
throw new Error "Internal structure cannot be transformed to dom"
@ -238,6 +315,51 @@ module.exports = (HB)->
new XmlType uid, tagname, attributes, elements, undefined
#
# @nodoc
# Defines an object that is cannot be changed. You can use this to set an immutable string, or a number.
#
class TextNodeType extends types.ImmutableObject
#
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
# @param {Object} content
#
constructor: (uid, content)->
if content._yatta?
d = new types.Delete undefined, content._yatta
HB.addOperation(d).execute()
content._yatta = null
content._yatta = @
super uid, content
applyDelete: (op)->
if @insert_parent? and not @insert_parent.isDeleted()
@insert_parent.applyDelete op
else
super
type: "TextNodeType"
#
# Encode this operation in such a way that it can be parsed by remote peers.
#
_encode: ()->
json = {
'type': @type
'uid' : @getUid()
'content' : @content.textContent
}
json
parser['TextNodeType'] = (json)->
{
'uid' : uid
'content' : content
} = json
textnode = document.createTextNode content
new TextNodeType uid, textnode
types['XmlType'] = XmlType

View File

@ -36,27 +36,36 @@ describe "XmlFramework", ->
@users = @yTest.users
###
@test_user = @yTest.makeNewUser 0, (Connector_uninitialized [])
test_users = []
connector = (Connector_uninitialized test_users)
@test_user = @yTest.makeNewUser 0, connector
test_users.push @test_user
# test_user_listen listens to the actions of test_user. He will update his dom when he receives from test_user.
@test_user_listen = @yTest.makeNewUser 2, connector
test_users.push @test_user_listen
@test_user2 = @yTest.makeNewUser 1, (Connector_uninitialized [])
$("#test_dom").replaceWith('<div id="test_dom" test_attribute="the test" class="stuffy" style="color: blue"><p id="replaceme">replace me</p><p id="removeme">remove me</p><p>This is a test object for <b>XmlFramework</b></p><span class="span_element"><p>span</p></span></div>')
@$dom = $("#test_dom")
@dom = @$dom[0]
@test_user.val(@dom)
@test_user_listen.getConnector().flushAll()
@test_user_listen_dom = @test_user_listen.val()
@check = ()=>
dom_ = @test_user.val(true)
expect(dom_.outerHTML).to.equal(@dom.outerHTML)
dom_ = @dom.outerHTML
# now test if other collaborators can parse the HB and result in the same content
hb = @test_user.HB._encode()
@test_user2.engine.applyOps(hb)
dom2 = @test_user2.val()
expect(dom_.outerHTML).to.equal(dom2.outerHTML)
expect(dom_).to.equal(dom2.outerHTML)
@test_user_listen.getConnector().flushAll()
expect(dom_).to.equal(@test_user_listen_dom.outerHTML)
done()
it "can transform to a new real Dom element", ->
dom_ = @test_user.val(true)
expect(dom_ isnt @dom).to.be.true
@check()
it "supports dom.insertBefore", ->
newdom = $("<p>dtrn</p>")[0]
@ -116,6 +125,7 @@ describe "XmlFramework", ->
it "supports jquery.appendTo", ->
$("<b>appendedTo</b>").appendTo("#test_dom p")
$("p").appendTo("#test_dom")
@check()
it "supports jquery.before", ->