insertBefore (xml), and prevent bug for addProperty-listener

This commit is contained in:
Kevin Jahns 2014-09-29 09:58:44 +02:00
parent 98b1a8f660
commit 03d652f70b
66 changed files with 32695 additions and 382 deletions

View File

@ -0,0 +1 @@
!function t(n,e,r){function i(u,a){if(!e[u]){if(!n[u]){var s="function"==typeof require&&require;if(!a&&s)return s(u,!0);if(o)return o(u,!0);throw new Error("Cannot find module '"+u+"'")}var c=e[u]={exports:{}};n[u][0].call(c.exports,function(t){var e=n[u][1][t];return i(e?e:t)},c,c.exports,t,n,e,r)}return e[u].exports}for(var o="function"==typeof require&&require,u=0;u<r.length;u++)i(r[u]);return i}({1:[function(t,n){var e;e=function(t,n){var e,r,i,o,u,a;return a=null,null!=n&&(a=n.iwcHandler),o={},r=new DUIClient,r.connect(function(t){var n;return null!=(n=o[t.action])&&n.map(function(n){return setTimeout(function(){return n(t)},0)}),null!=a?a(t):void 0}),r.initOK(),u=null,e=function(){function t(t,n,e,i){var a,s,c,l;this.engine=t,this.HB=n,this.execution_listener=e,this.yatta=i,this.duiClient=r,this.iwcHandler=o,l=function(t){return function(n){return 0!==Object.getOwnPropertyNames(t.initialized).length?t.send(n):void 0}}(this),this.execution_listener.push(l),this.initialized={},a=function(t){return function(e){var r;return n=e.extras.HB,r=e.extras.user,t.engine.applyOpsCheckDouble(n),t.initialized[r]=!0}}(this),o.Yatta_push_HB_element=[a],this.sendIwcIntent("Yatta_get_HB_element",this.HB.getOperationCounter()),s=function(t){return function(n){var e;return e=n.extras,null!=t.initialized[e.uid.creator]?t.receive(e):void 0}}(this),this.iwcHandler.Yatta_new_operation=[s],null!=u&&this.engine.applyOpsCheckDouble(u),c=function(t){return function(n){var e,r;return r=n.extras,console.log(r),e={HB:t.yatta.getHistoryBuffer()._encode(r),user:t.yatta.getUserId()},t.sendIwcIntent("Yatta_push_HB_element",e)}}(this),this.iwcHandler.Yatta_get_HB_element=[c]}return t.prototype.setIwcHandler=function(t){return a=t},t.prototype.sendIwcIntent=function(t,n){var e;return e=null,arguments.length>=2?(t=arguments[0],n=arguments[1],e={action:t,component:"",data:"",dataType:"",flags:["PUBLISH_GLOBAL"],extras:n}):e=arguments[0],this.duiClient.sendIntent(e)},t.prototype.send=function(t){return t.uid.creator===this.HB.getUserId()&&"string"!=typeof t.uid.op_number?this.sendIwcIntent("Yatta_new_operation",t):void 0},t.prototype.receive=function(t){return t.uid.creator!==this.HB.getUserId()?this.engine.applyOp(t):void 0},t}(),i=function(){var n;return n=Math.floor(1e6*Math.random()),t(e,n)},setTimeout(i,5e3),void 0},n.exports=e,"undefined"!=typeof window&&null!==window&&(null==window.Y&&(window.Y={}),window.Y.createIwcConnector=e)},{}]},{},[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

@ -28,7 +28,7 @@
send_ = (function(_this) {
return function(o) {
var conn, conn_id, _ref, _results;
if (o.creator === _this.HB.getUserId() && (typeof o.uid.op_number !== "string") && o.uid.sync) {
if (o.uid.creator === _this.HB.getUserId() && (typeof o.uid.op_number !== "string")) {
_ref = _this.connections;
_results = [];
for (conn_id in _ref) {
@ -71,7 +71,7 @@
} else if (data.HB != null) {
initialized_me = true;
_this.engine.applyOpsCheckDouble(data.HB, data.state_vector);
_this.engine.applyOpsCheckDouble(data.HB);
return conn.send({
conns: _this.getAllConnectionIds()
});
@ -88,8 +88,7 @@
} else if (data.state_vector != null) {
if (!initialized_him) {
conn.send({
HB: _this.yatta.getHistoryBuffer()._encode(data.state_vector),
state_vector: _this.yatta.HB.getOperationCounter()
HB: _this.yatta.getHistoryBuffer()._encode(data.state_vector)
});
return initialized_him = true;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,85 @@
(function() {
var Engine, HistoryBuffer, XmlFramework, json_types_uninitialized;
json_types_uninitialized = require("../Types/XmlTypes");
HistoryBuffer = require("../HistoryBuffer");
Engine = require("../Engine");
XmlFramework = (function() {
function XmlFramework(user_id, Connector) {
var beg, end, type_manager, uid_beg, uid_end;
this.HB = new HistoryBuffer(user_id);
type_manager = json_types_uninitialized(this.HB);
this.types = type_manager.types;
this.engine = new Engine(this.HB, type_manager.parser);
this.HB.engine = this.engine;
this.connector = new Connector(this.engine, this.HB, type_manager.execution_listener, this);
uid_beg = this.HB.getReservedUniqueIdentifier();
uid_end = this.HB.getReservedUniqueIdentifier();
beg = this.HB.addOperation(new this.types.Delimiter(uid_beg, void 0, uid_end)).execute();
end = this.HB.addOperation(new this.types.Delimiter(uid_end, beg, void 0)).execute();
this.root_element = new this.types.ReplaceManager(void 0, this.HB.getReservedUniqueIdentifier(), beg, end);
this.HB.addOperation(this.root_element).execute();
}
XmlFramework.prototype.getSharedObject = function() {
return this.root_element.val();
};
XmlFramework.prototype.getConnector = function() {
return this.connector;
};
XmlFramework.prototype.getHistoryBuffer = function() {
return this.HB;
};
XmlFramework.prototype.setMutableDefault = function(mutable) {
return this.getSharedObject().setMutableDefault(mutable);
};
XmlFramework.prototype.getUserId = function() {
return this.HB.getUserId();
};
XmlFramework.prototype.toJson = function() {
return this.getSharedObject().toJson();
};
XmlFramework.prototype.val = function() {
var newXml;
if ((arguments.length === 0) || (typeof arguments[0] === "boolean")) {
return this.getSharedObject().val(arguments[0]);
} else if (arguments.length === 1) {
newXml = new this.types.XmlType(void 0, void 0, void 0, void 0, arguments[0]);
this.HB.addOperation(newXml).execute();
this.root_element.replace(newXml);
return newXml;
} else {
throw new Error("can only parse 0, or 1 parameter!");
}
};
XmlFramework.prototype.on = function() {
var _ref;
return (_ref = this.getSharedObject()).on.apply(_ref, arguments);
};
return XmlFramework;
})();
module.exports = XmlFramework;
if (typeof window !== "undefined" && window !== null) {
if (window.Y == null) {
window.Y = {};
}
window.Y.XmlFramework = XmlFramework;
}
}).call(this);
//# sourceMappingURL=../Frameworks/XmlFramework.js.map

File diff suppressed because one or more lines are too long

View File

@ -12,12 +12,13 @@
this.is_deleted = false;
this.doSync = true;
this.garbage_collected = false;
if (uid != null) {
this.doSync = !isNaN(parseInt(uid.op_number));
} else {
if (uid == null) {
uid = HB.getNextOperationIdentifier();
}
this.creator = uid['creator'], this.op_number = uid['op_number'];
if (uid.doSync == null) {
uid.doSync = !isNaN(parseInt(uid.op_number));
}
this.creator = uid['creator'], this.op_number = uid['op_number'], this.doSync = uid['doSync'];
}
Operation.prototype.type = "Insert";
@ -217,34 +218,32 @@
Insert.prototype.type = "Insert";
Insert.prototype.applyDelete = function(o) {
var garbagecollect;
var garbagecollect, _ref;
if (this.deleted_by == null) {
this.deleted_by = [];
}
if ((this.parent != null) && !this.isDeleted()) {
if (o != null) {
this.parent.callEvent("delete", this, o);
}
this.parent.callEvent("delete", this, o);
}
if (o != null) {
this.deleted_by.push(o);
}
garbagecollect = false;
if (this.prev_cl.isDeleted()) {
if (!((this.prev_cl != null) && (this.next_cl != null)) || this.prev_cl.isDeleted()) {
garbagecollect = true;
}
Insert.__super__.applyDelete.call(this, garbagecollect);
if (this.next_cl.isDeleted()) {
if ((_ref = this.next_cl) != null ? _ref.isDeleted() : void 0) {
return this.next_cl.applyDelete();
}
};
Insert.prototype.cleanup = function() {
var d, o, _i, _len, _ref;
if (this.prev_cl.isDeleted()) {
_ref = this.deleted_by;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
d = _ref[_i];
var d, o, _i, _len, _ref, _ref1;
if ((_ref = this.prev_cl) != null ? _ref.isDeleted() : void 0) {
_ref1 = this.deleted_by;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
d = _ref1[_i];
d.cleanup();
}
o = this.next_cl;
@ -274,8 +273,11 @@
return d;
};
Insert.prototype.execute = function() {
Insert.prototype.execute = function(fire_event) {
var distance_to_origin, i, o, parent, _ref;
if (fire_event == null) {
fire_event = true;
}
if (!this.validateSavedOperations()) {
return false;
} else {
@ -313,7 +315,7 @@
this.next_cl.prev_cl = this;
}
parent = (_ref = this.prev_cl) != null ? _ref.getParent() : void 0;
if (parent != null) {
if ((parent != null) && fire_event) {
this.setParent(parent);
this.parent.callEvent("insert", this);
}

File diff suppressed because one or more lines are too long

View File

@ -255,9 +255,7 @@
}
});
addPropertyListener = function(event, op) {
if (op.next_cl instanceof types.Delimiter && op.prev_cl instanceof types.Delimiter) {
repl_manager.parent.callEvent('addProperty', property_name, op);
}
repl_manager.parent.callEvent('addProperty', property_name, op);
return repl_manager.deleteListener('addProperty', addPropertyListener);
};
this.on('insert', addPropertyListener);
@ -323,7 +321,6 @@
this.content.applyDelete();
this.content.dontSync();
}
this.beforeDelete = this.content;
this.content = null;
return Replaceable.__super__.applyDelete.apply(this, arguments);
};
@ -342,7 +339,7 @@
_ref.setReplaceManager(this.parent);
}
}
ins_result = Replaceable.__super__.execute.call(this);
ins_result = Replaceable.__super__.execute.call(this, this.content != null);
if (ins_result) {
if (this.next_cl.type === "Delimiter" && this.prev_cl.type !== "Delimiter") {
this.prev_cl.applyDelete();

File diff suppressed because one or more lines are too long

View File

@ -101,23 +101,37 @@
return WordType.__super__.cleanup.call(this);
};
WordType.prototype.insertText = function(position, content) {
var c, ith, left, op, right, _i, _len;
ith = this.getOperationByPosition(position);
left = ith.prev_cl;
WordType.prototype.push = function(content) {
return this.insertAfter(this.end.prev_cl, content);
};
WordType.prototype.insertAfter = function(left, content) {
var c, op, right, _i, _len;
while (left.isDeleted()) {
left = left.prev_cl;
}
right = left.next_cl;
for (_i = 0, _len = content.length; _i < _len; _i++) {
c = content[_i];
op = new TextInsert(c, void 0, left, right);
if (content.type != null) {
op = new TextInsert(content, void 0, left, right);
HB.addOperation(op).execute();
left = op;
} else {
for (_i = 0, _len = content.length; _i < _len; _i++) {
c = content[_i];
op = new TextInsert(c, void 0, left, right);
HB.addOperation(op).execute();
left = op;
}
}
return this;
};
WordType.prototype.insertText = function(position, content) {
var ith, left;
ith = this.getOperationByPosition(position);
left = ith.prev_cl;
return this.insertAfter(left, content);
};
WordType.prototype.deleteText = function(position, length) {
var d, delete_ops, i, o, _i;
o = this.getOperationByPosition(position);
@ -174,12 +188,16 @@
WordType.prototype.setReplaceManager = function(op) {
this.saveOperation('replace_manager', op);
this.validateSavedOperations();
this.on('insert', function(event, ins) {
return op.forwardEvent(this, 'change', ins);
});
this.on('insert', (function(_this) {
return function(event, ins) {
var _ref;
return (_ref = _this.replace_manager) != null ? _ref.forwardEvent(_this, 'change', ins) : void 0;
};
})(this));
return this.on('delete', (function(_this) {
return function(event, ins, del) {
return op.forwardEvent(_this, 'change', del);
var _ref;
return (_ref = _this.replace_manager) != null ? _ref.forwardEvent(_this, 'change', del) : void 0;
};
})(this));
};

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,193 @@
(function() {
var json_types_uninitialized,
__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; };
json_types_uninitialized = require("./JsonTypes");
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() {
f.apply(this, arguments);
return old_f.apply(this, arguments);
};
} else {
return this[f_name] = f;
}
};
}
module.exports = function(HB) {
var XmlType, json_types, parser, types;
json_types = json_types_uninitialized(HB);
types = json_types.types;
parser = json_types.parser;
XmlType = (function(_super) {
__extends(XmlType, _super);
function XmlType(uid, tagname, attributes, elements, xml, prev, next, origin) {
var attr, element, i, last, n, word, _i, _j, _len, _ref, _ref1;
this.tagname = tagname;
this.xml = xml;
if ((prev != null) && (next == null) && (prev.type != null)) {
while (prev.isDeleted()) {
prev = prev.prev_cl;
}
next = prev.next_cl;
}
XmlType.__super__.constructor.call(this, uid, prev, next, origin);
if ((attributes != null) && (elements != null)) {
this.saveOperation('attributes', attributes);
this.saveOperation('elements', elements);
} else if ((attributes == null) && (elements == null)) {
this.attributes = new types.JsonType();
HB.addOperation(this.attributes).execute();
this.elements = new types.WordType();
this.elements.parent = this;
HB.addOperation(this.elements).execute();
} else {
throw new Error("Either define attribute and elements both, or none of them");
}
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) {
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];
if (n.nodeType === n.TEXT_NODE) {
word = new types.WordType();
HB.addOperation(word).execute();
word.push(n.textContent);
this.elements.push(word);
} else if (n.nodeType === n.ELEMENT_NODE) {
last = this.elements.end;
element = new XmlType(void 0, void 0, void 0, void 0, n, last.prev_cl, last);
HB.addOperation(element).execute();
this.elements.push(element);
} else {
throw new Error("I don't know Node-type " + n.nodeType + "!!");
}
}
this.setXmlProxy();
}
void 0;
}
XmlType.prototype.type = "XmlType";
XmlType.prototype.applyDelete = function() {
this.attributes.applyDelete();
this.elements.applyDelete();
return XmlType.__super__.applyDelete.call(this);
};
XmlType.prototype.cleanup = function() {
return XmlType.__super__.cleanup.call(this);
};
XmlType.prototype.setXmlProxy = function() {
this.xml._yatta = this;
return this.xml._proxy('insertBefore', function(insertedNode, adjacentNode) {
var element, next, prev;
next = adjacentNode != null ? adjacentNode._yatta : void 0;
prev = null;
if (next != null) {
prev = next.prev_cl;
} else {
prev = this._yatta.elements.end.prev_cl;
}
element = new XmlType(void 0, void 0, void 0, void 0, insertedNode, prev);
return HB.addOperation(element).execute();
});
};
XmlType.prototype.val = function(enforce) {
var a, attr, attr_name, e, n, text_node, value;
if (enforce == null) {
enforce = false;
}
if (typeof document !== "undefined" && document !== null) {
if ((this.xml == null) || enforce) {
this.xml = document.createElement(this.tagname);
attr = this.attributes.val();
for (attr_name in attr) {
value = attr[attr_name];
a = document.createAttribute(attr_name);
a.value = value;
this.xml.setAttributeNode(a);
}
e = this.elements.beginning.next_cl;
while (e.type !== "Delimiter") {
n = e.content;
if (!n.isDeleted()) {
if (n.type === "XmlType") {
this.xml.appendChild(n.val(enforce));
} else if (n.type === "WordType") {
text_node = document.createTextNode(n.val());
this.xml.appendChild(text_node);
} else {
throw new Error("Internal structure cannot be transformed to dom");
}
}
e = e.next_cl;
}
}
this.setXmlProxy();
return this.xml;
}
};
XmlType.prototype.execute = function() {
return XmlType.__super__.execute.apply(this, arguments);
};
/*
if not @validateSavedOperations()
return false
else
return true
*/
XmlType.prototype.getParent = function() {
return this.parent;
};
XmlType.prototype._encode = function() {
var json, _ref, _ref1, _ref2;
json = {
'type': this.type,
'attributes': this.attributes.getUid(),
'elements': this.elements.getUid(),
'tagname': this.tagname,
'uid': this.getUid(),
'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0,
'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0
};
if (this.origin !== this.prev_cl) {
json["origin"] = (_ref2 = this.origin) != null ? _ref2.getUid() : void 0;
}
return json;
};
return XmlType;
})(types.Insert);
parser['XmlType'] = function(json) {
var attributes, elements, next, origin, prev, tagname, uid;
uid = json['uid'], attributes = json['attributes'], elements = json['elements'], tagname = json['tagname'], prev = json['prev'], next = json['next'], origin = json['origin'];
return new XmlType(uid, tagname, attributes, elements, void 0, prev, next, origin);
};
types['XmlType'] = XmlType;
return json_types;
};
}).call(this);

File diff suppressed because one or more lines are too long

View File

@ -7,6 +7,8 @@
exports['TextFramework'] = require('./Frameworks/TextFramework');
exports['XmlFramework'] = require('./Frameworks/XmlFramework');
}).call(this);
//# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"sources":["index.coffee"],"names":[],"mappings":"AAEA;AAAA,EAAA,OAAQ,CAAA,cAAA,CAAR,GACE,OAAA,CAAQ,2BAAR,CADF,CAAA;;AAAA,EAEA,OAAQ,CAAA,eAAA,CAAR,GACE,OAAA,CAAQ,4BAAR,CAHF,CAAA;;AAAA,EAIA,OAAQ,CAAA,eAAA,CAAR,GACE,OAAA,CAAQ,4BAAR,CALF,CAAA;;AAAA,EAMA,OAAQ,CAAA,eAAA,CAAR,GACE,OAAA,CAAQ,4BAAR,CAPF,CAAA;AAAA","file":"index.js","sourceRoot":"/source/","sourcesContent":["\n\nexports['IwcConnector'] =\n require './Connectors/IwcConnector'\nexports['TestConnector'] =\n require './Connectors/TestConnector'\nexports['JsonFramework'] =\n require './Frameworks/JsonFramework'\nexports['TextFramework'] =\n require './Frameworks/TextFramework'\n\n"]}
{"version":3,"sources":["index.coffee"],"names":[],"mappings":"AAEA;AAAA,EAAA,OAAQ,CAAA,cAAA,CAAR,GACE,OAAA,CAAQ,2BAAR,CADF,CAAA;;AAAA,EAEA,OAAQ,CAAA,eAAA,CAAR,GACE,OAAA,CAAQ,4BAAR,CAHF,CAAA;;AAAA,EAIA,OAAQ,CAAA,eAAA,CAAR,GACE,OAAA,CAAQ,4BAAR,CALF,CAAA;;AAAA,EAMA,OAAQ,CAAA,eAAA,CAAR,GACE,OAAA,CAAQ,4BAAR,CAPF,CAAA;;AAAA,EAQA,OAAQ,CAAA,cAAA,CAAR,GACE,OAAA,CAAQ,2BAAR,CATF,CAAA;AAAA","file":"index.js","sourceRoot":"/source/","sourcesContent":["\n\nexports['IwcConnector'] =\n require './Connectors/IwcConnector'\nexports['TestConnector'] =\n require './Connectors/TestConnector'\nexports['JsonFramework'] =\n require './Frameworks/JsonFramework'\nexports['TextFramework'] =\n require './Frameworks/TextFramework'\nexports['XmlFramework'] =\n require './Frameworks/XmlFramework'\n\n"]}

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

@ -6,13 +6,21 @@
</head>
<body>
<div id="mocha"></div>
<script src="../../node_modules/mocha/mocha.js"></script>
<script>mocha.setup('bdd')</script>
<script src="TextYatta_test.js"></script>
<script src="JsonYatta_test.js"></script>
<div id="test_dom"><p>This is a test object for <b>XmlFramework</b></p></div>
<script src="../../node_modules/mocha/mocha.js" class="awesome"></script>
<script>
mocha.checkLeaks();
mocha.run();
mocha.setup('bdd');
mocha.ui('bdd');
mocha.reporter('html');
</script>
<!--script src="TextYatta_test.js"></script>
<script src="JsonYatta_test.js"></script-->
<script src="XmlYatta_test_browser.js"></script>
<script>
//mocha.checkLeaks();
//mocha.run();
if (window.mochaPhantomJS) { mochaPhantomJS.run(); }
else { mocha.run(); }
</script>
</body>
</html>

View File

@ -95,6 +95,11 @@
<ul>
<li class='letter'>x</li>
<ul>
<li>
<a href='class/XmlFramework.html'>
XmlFramework
</a>
</li>
<li>
<a href='class/XmlType.html'>
XmlType
@ -244,6 +249,14 @@
<ul>
<li class='letter'>x</li>
<ul>
<li>
<a href='file/lib/Frameworks/XmlFramework.coffee.html'>
XmlFramework.coffee
</a>
<small>
(lib&#47;Frameworks)
</small>
</li>
<li>
<a href='file/lib/Types/XmlTypes.coffee.html'>
XmlTypes.coffee
@ -258,7 +271,7 @@
</div>
</div>
<div id='footer'>
September 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -222,7 +222,7 @@ on how to do that with urls.</p>
</div>
</div>
<div id='footer'>
September 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -99,6 +99,28 @@ if (x.type === &quot;WordType&quot;) {
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#push-dynamic'>
#
(void)
<b>push</b><span>(content)</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#insertAfter-dynamic'>
#
(void)
<b>insertAfter</b><span>(left, content)</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#insertText-dynamic'>
@ -245,6 +267,24 @@ if (x.type === &quot;WordType&quot;) {
<br>
</p>
</div>
<div class='method_details'>
<p class='signature' id='push-dynamic'>
#
(void)
<b>push</b><span>(content)</span>
<br>
</p>
</div>
<div class='method_details'>
<p class='signature' id='insertAfter-dynamic'>
#
(void)
<b>insertAfter</b><span>(left, content)</span>
<br>
</p>
</div>
<div class='method_details'>
<p class='signature' id='insertText-dynamic'>
@ -415,7 +455,7 @@ yatta.bind(textbox);</code></pre>
</div>
</div>
<div id='footer'>
September 26, 14 11:52:44 by
September 29, 14 09:30:23 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -85,12 +85,23 @@ Use it in order to check whether this is an xml-type or something else.</p>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#setXmlProxy-dynamic'>
#
(void)
<b>setXmlProxy</b><span>()</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#val-dynamic'>
#
(void)
<b>val</b><span>()</span>
<b>val</b><span>(enforce = false)</span>
</a>
</span>
<span class='desc'>
@ -140,7 +151,7 @@ Use it in order to check whether this is an xml-type or something else.</p>
<p class='signature' id='constructor-dynamic'>
#
(void)
<b>constructor</b><span>(uid, tagname, attributes, elements, prev_cl, next_cl, origin)</span>
<b>constructor</b><span>(uid, tagname, attributes, elements, xml, prev, next, origin)</span>
<br>
</p>
@ -165,12 +176,21 @@ Use it in order to check whether this is an xml-type or something else.</p>
<br>
</p>
</div>
<div class='method_details'>
<p class='signature' id='setXmlProxy-dynamic'>
#
(void)
<b>setXmlProxy</b><span>()</span>
<br>
</p>
</div>
<div class='method_details'>
<p class='signature' id='val-dynamic'>
#
(void)
<b>val</b><span>()</span>
<b>val</b><span>(enforce = false)</span>
<br>
</p>
@ -232,7 +252,7 @@ This result can be send to other clients.</p>
</div>
</div>
<div id='footer'>
September 26, 14 11:52:44 by
September 29, 14 09:30:23 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -61,6 +61,14 @@
</small>
</li>
<li>
<a href='class/XmlFramework.html' target='main'>
XmlFramework
</a>
<small class='namespace'>
</small>
</li>
<li>
<a href='class/JsonTypeWrapper.html' target='main'>
JsonTypeWrapper

View File

@ -38,7 +38,7 @@
</div>
</div>
<div id='footer'>
September 26, 14 11:52:44 by
September 29, 14 09:30:23 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;&#108;&#x74;&#x6f;&#58;&#107;&#x65;&#118;&#105;&#110;&#46;&#106;&#97;&#104;&#x6e;&#115;&#64;&#114;&#x77;&#x74;&#x68;&#45;&#97;&#x61;&#99;&#104;&#x65;&#x6e;&#x2e;&#x64;&#x65;">&#107;&#x65;&#118;&#105;&#110;&#46;&#106;&#97;&#104;&#x6e;&#115;&#64;&#114;&#x77;&#x74;&#x68;&#45;&#97;&#x61;&#99;&#104;&#x65;&#x6e;&#x2e;&#x64;&#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;&#x6f;&#58;&#x6b;&#x65;&#118;&#x69;&#110;&#46;&#x6a;&#x61;&#104;&#110;&#x73;&#64;&#114;&#x77;&#116;&#104;&#x2d;&#x61;&#x61;&#x63;&#104;&#x65;&#x6e;&#x2e;&#x64;&#101;">&#x6b;&#x65;&#118;&#x69;&#110;&#46;&#x6a;&#x61;&#104;&#110;&#x73;&#64;&#114;&#x77;&#116;&#104;&#x2d;&#x61;&#x61;&#x63;&#104;&#x65;&#x6e;&#x2e;&#x64;&#101;</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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

@ -37,9 +37,35 @@
<td>lib&#47;Types</td>
</tr>
</table>
<h2>Method Summary</h2>
<ul class='summary'>
<li>
<span class='signature'>
<a href='#Element-'>
~
(void)
<b>Element</b><span>(f_name, f)</span>
</a>
</span>
<span class='desc'>
</span>
</li>
</ul>
<h2>Method Details</h2>
<div class='methods'>
<div class='method_details'>
<p class='signature' id='Element-'>
~
(void)
<b>Element</b><span>(f_name, f)</span>
<br>
</p>
</div>
</div>
</div>
<div id='footer'>
September 26, 14 11:52:44 by
September 29, 14 09:30:23 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 26, 14 11:52:44 by
September 29, 14 09:30:23 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>

View File

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

File diff suppressed because one or more lines are too long

View File

@ -29,6 +29,14 @@
<input type='text'>
</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'>
#_encode
@ -62,11 +70,11 @@
</small>
</li>
<li>
<a href='class/WordType.html#applyDelete-dynamic' target='main' title='applyDelete'>
<a href='class/JsonType.html#applyDelete-dynamic' target='main' title='applyDelete'>
#applyDelete
</a>
<small>
(WordType)
(JsonType)
</small>
</li>
<li>
@ -78,17 +86,9 @@
</small>
</li>
<li>
<a href='class/JsonType.html#applyDelete-dynamic' target='main' title='applyDelete'>
<a href='class/WordType.html#applyDelete-dynamic' target='main' title='applyDelete'>
#applyDelete
</a>
<small>
(JsonType)
</small>
</li>
<li>
<a href='class/WordType.html#bind-dynamic' target='main' title='bind'>
#bind
</a>
<small>
(WordType)
</small>
@ -102,16 +102,8 @@
</small>
</li>
<li>
<a href='class/XmlType.html#cleanup-dynamic' target='main' title='cleanup'>
#cleanup
</a>
<small>
(XmlType)
</small>
</li>
<li>
<a href='class/WordType.html#cleanup-dynamic' target='main' title='cleanup'>
#cleanup
<a href='class/WordType.html#bind-dynamic' target='main' title='bind'>
#bind
</a>
<small>
(WordType)
@ -125,6 +117,22 @@
(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,6 +149,14 @@
(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
@ -157,14 +173,6 @@
(IwcConnector)
</small>
</li>
<li>
<a href='class/XmlType.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(XmlType)
</small>
</li>
<li>
<a href='class/JsonType.html#constructor-dynamic' target='main' title='constructor'>
#constructor
@ -181,6 +189,14 @@
(JsonTypeWrapper)
</small>
</li>
<li>
<a href='class/XmlFramework.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#constructor-dynamic' target='main' title='constructor'>
#constructor
@ -253,6 +269,14 @@
(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
@ -262,11 +286,19 @@
</small>
</li>
<li>
<a href='class/TextFramework.html#getConnector-dynamic' target='main' title='getConnector'>
<a href='class/XmlFramework.html#getConnector-dynamic' target='main' title='getConnector'>
#getConnector
</a>
<small>
(TextFramework)
(XmlFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#getHistoryBuffer-dynamic' target='main' title='getHistoryBuffer'>
#getHistoryBuffer
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
@ -285,6 +317,14 @@
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonType.html#getParent-dynamic' target='main' title='getParent'>
#getParent
</a>
<small>
(JsonType)
</small>
</li>
<li>
<a href='class/XmlType.html#getParent-dynamic' target='main' title='getParent'>
#getParent
@ -294,11 +334,11 @@
</small>
</li>
<li>
<a href='class/JsonType.html#getParent-dynamic' target='main' title='getParent'>
#getParent
<a href='class/XmlFramework.html#getSharedObject-dynamic' target='main' title='getSharedObject'>
#getSharedObject
</a>
<small>
(JsonType)
(XmlFramework)
</small>
</li>
<li>
@ -318,11 +358,11 @@
</small>
</li>
<li>
<a href='class/JsonFramework.html#getUserId-dynamic' target='main' title='getUserId'>
<a href='class/XmlFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId
</a>
<small>
(JsonFramework)
(XmlFramework)
</small>
</li>
<li>
@ -334,8 +374,16 @@
</small>
</li>
<li>
<a href='class/WordType.html#insertText-dynamic' target='main' title='insertText'>
#insertText
<a href='class/JsonFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId
</a>
<small>
(JsonFramework)
</small>
</li>
<li>
<a href='class/WordType.html#insertAfter-dynamic' target='main' title='insertAfter'>
#insertAfter
</a>
<small>
(WordType)
@ -350,11 +398,19 @@
</small>
</li>
<li>
<a href='class/JsonFramework.html#on-dynamic' target='main' title='on'>
<a href='class/WordType.html#insertText-dynamic' target='main' title='insertText'>
#insertText
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/XmlFramework.html#on-dynamic' target='main' title='on'>
#on
</a>
<small>
(JsonFramework)
(XmlFramework)
</small>
</li>
<li>
@ -365,6 +421,22 @@
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#on-dynamic' target='main' title='on'>
#on
</a>
<small>
(JsonFramework)
</small>
</li>
<li>
<a href='class/WordType.html#push-dynamic' target='main' title='push'>
#push
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/IwcConnector.html#receive-dynamic' target='main' title='receive'>
#receive
@ -413,6 +485,14 @@
(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
@ -445,6 +525,22 @@
(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
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#toJson-dynamic' target='main' title='toJson'>
#toJson
@ -469,6 +565,14 @@
(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
@ -493,14 +597,6 @@
(JsonFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#val-dynamic' target='main' title='val'>
#val
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonType.html#val-dynamic' target='main' title='val'>
#val
@ -509,6 +605,14 @@
(JsonType)
</small>
</li>
<li>
<a href='class/XmlFramework.html#val-dynamic' target='main' title='val'>
#val
</a>
<small>
(XmlFramework)
</small>
</li>
</ul>
</div>
</body>

View File

@ -0,0 +1,32 @@
## PeerJs + JSON Example
Here, I will give a short overview on how to enable collaborative json with the
[PeerJs](http://peerjs.com/) Connector and the Json Framework. Open
[index.html](http://dadamonad.github.io/Yatta/examples/PeerJs-Json/index.html) in your Browser and
use the console to explore Yatta!
[PeerJs](http://peerjs.com) is a Framework that enables you to connect to other peers. You just need the
user-id of the peer (browser/client). And then you can connect to it.
First you have to include the following libraries in your html file:
```
<script src="http://cdn.peerjs.com/0.3/peer.js"></script>
<script src="../../build/browser/Frameworks/XmlFramework.js"></script>
<script src="../../build/browser/Connectors/PeerJsConnector.js"></script>
<script src="./index.js"></script>
```
### Create Connector
The PeerJs Framework requires an API key, or you need to set up your own PeerJs server.
Get an API key from the [Website](http://peerjs.com/peerserver).
The first parameter of `createPeerJsConnector` is forwarded as the options object in PeerJs.
Therefore, you may also specify the server/port here, if you have set up your own server.
```js
var yatta, yattaHandler;
Y.createPeerJsConnector({key: 'h7nlefbgavh1tt9'}, function(Connector, user_id){
yatta = new Y.XmlFramework(user_id, Connector);
console.log(yatta.getUserId());
});
```

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>PeerJs Json Example</title>
<script src="http://cdn.peerjs.com/0.3/peer.js"></script>
<script src="../../build/browser/Frameworks/XmlFramework.js"></script>
<script src="../../build/browser/Connectors/PeerJsConnector.js"></script>
<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>
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>.
</p>
</body>
</html>

View File

@ -0,0 +1,31 @@
/**
## PeerJs + JSON Example
Here, I will give a short overview on how to enable collaborative json with the
[PeerJs](http://peerjs.com/) Connector and the Json Framework. Open
[index.html](http://dadamonad.github.io/Yatta/examples/PeerJs-Json/index.html) in your Browser and
use the console to explore Yatta!
[PeerJs](http://peerjs.com) is a Framework that enables you to connect to other peers. You just need the
user-id of the peer (browser/client). And then you can connect to it.
First you have to include the following libraries in your html file:
```
<script src="http://cdn.peerjs.com/0.3/peer.js"></script>
<script src="../../build/browser/Frameworks/XmlFramework.js"></script>
<script src="../../build/browser/Connectors/PeerJsConnector.js"></script>
<script src="./index.js"></script>
```
### Create Connector
The PeerJs Framework requires an API key, or you need to set up your own PeerJs server.
Get an API key from the [Website](http://peerjs.com/peerserver).
The first parameter of `createPeerJsConnector` is forwarded as the options object in PeerJs.
Therefore, you may also specify the server/port here, if you have set up your own server.
*/
var yatta, yattaHandler;
Y.createPeerJsConnector({key: 'h7nlefbgavh1tt9'}, function(Connector, user_id){
yatta = new Y.XmlFramework(user_id, Connector);
console.log(yatta.getUserId());
});

View File

@ -42,7 +42,26 @@ it will be instantly shared with all the other collaborators.
```js
yatta = new Y.JsonFramework(user_id, Connector);
yatta.val('w','w');
console.log(yatta.getUserId());
function show(o){
if (o.type === "JsonType"){
return JSON.stringify(o.toJson());
} else if (o.type === "WordType") {
return o.val();
} else if (o.constructor === {}.constructor) { // It's an Object
return JSON.stringify(o);
} else { // It's a primitive data type (E.g. string, int)
return o;
}
}
function addProperty(event_name, property_name, op){
// op is the operation that changed the objects value. In addProperty it is most likely to be a 'Replaceable' (see doc).
console.log("Property '" + property_name + "' was created by '"+op.creator+"'!");
console.log("Value: " + show(this.val(property_name))); // 'this' is the object on which the property was created.
};
yatta.on('addProperty', addProperty);
});
```

View File

@ -14,6 +14,8 @@ coffeelint = require 'gulp-coffeelint'
mocha = require 'gulp-mocha'
run = require 'gulp-run'
ljs = require 'gulp-ljs'
mochaPhantomJS = require 'gulp-mocha-phantomjs'
gulp.task 'default', ['lint', 'browser', 'test', 'literate', 'lib', 'codo']
@ -24,6 +26,7 @@ files =
build : ['./build/**']
browser : ['./lib/{Connectors,Frameworks}/**/*']
test : ['./test/**/*_test.coffee']
browser_test : ['./test/**/*_test_browser.coffee']
gulp : ['./gulpfile.coffee']
examples : ['./examples/**/*.js']
@ -55,7 +58,7 @@ gulp.task 'browser', ->
.pipe gulp.dest 'build/browser'
.pipe gulpif '!**/', git.add({args : "-A"})
gulp.src files.test, {read: false}
gulp.src (files.test.concat files.browser_test), {read: false}
.pipe browserify
transform: ['coffeeify']
extensions: ['.coffee']
@ -91,6 +94,9 @@ gulp.task 'watch', ['default'], ->
gulp.watch files.test, ['test']
gulp.watch files.examples, ['literate']
gulp.task 'phantom_watch', ['phantom_test'], ->
gulp.watch files.all, ['phantom_test']
gulp.task 'literate', ->
gulp.src files.examples
.pipe ljs { code : true }
@ -103,10 +109,14 @@ gulp.task 'literate', ->
gulp.task 'upload', [], ()->
run('scp -r ./build ./examples jahns@manet.informatik.rwth-aachen.de:/home/jahns/public_html/collaborative_preview/').exec()
gulp.task 'codo', [], ()->
gulp.task 'codo', [], ()->
command = 'codo -o "./doc" --name "Yatta!" --readme "README.md" --undocumented false --private true --title "Yatta! API" ./lib - LICENSE.txt '
run(command).exec()
gulp.task 'phantom_test', ['browser'], ()->
gulp.src 'build/test/index.html'
.pipe mochaPhantomJS()
gulp.task 'clean', ->
gulp.src './build/{browser,test,node}/**/*.{js,map}', { read: false }
.pipe ignore '*.html'

View File

@ -0,0 +1,100 @@
json_types_uninitialized = require "../Types/XmlTypes"
HistoryBuffer = require "../HistoryBuffer"
Engine = require "../Engine"
#
# Framework for Xml-like data-structures.
# Known values that are supported:
#
class XmlFramework
#
# @param {String} user_id Unique id of the peer.
# @param {Connector} Connector the connector class.
#
constructor: (user_id, Connector)->
@HB = new HistoryBuffer user_id
type_manager = json_types_uninitialized @HB
@types = type_manager.types
@engine = new Engine @HB, type_manager.parser
@HB.engine = @engine # TODO: !! only for debugging
@connector = new Connector @engine, @HB, type_manager.execution_listener, @
#first_word = new @types.XmlType(undefined, undefined, undefined, undefined, document.createElement("shared"))
#@HB.addOperation(first_word).execute()
uid_beg = @HB.getReservedUniqueIdentifier()
uid_end = @HB.getReservedUniqueIdentifier()
beg = @HB.addOperation(new @types.Delimiter uid_beg, undefined, uid_end).execute()
end = @HB.addOperation(new @types.Delimiter uid_end, beg, undefined).execute()
@root_element = new @types.ReplaceManager undefined, @HB.getReservedUniqueIdentifier(), beg, end
@HB.addOperation(@root_element).execute()
#@root_element.replace first_word
#
# @return JsonType
#
getSharedObject: ()->
@root_element.val()
#
# Get the initialized connector.
#
getConnector: ()->
@connector
#
# @see HistoryBuffer
#
getHistoryBuffer: ()->
@HB
#
# @see JsonType.setMutableDefault
#
setMutableDefault: (mutable)->
@getSharedObject().setMutableDefault(mutable)
#
# Get the UserId from the HistoryBuffer object.
# In most cases this will be the same as the user_id value with which
# JsonFramework was initialized (Depending on the HistoryBuffer implementation).
#
getUserId: ()->
@HB.getUserId()
#
# @see JsonType.toJson
#
toJson : ()->
@getSharedObject().toJson()
#
# @see JsonType.val
#
val : ()->
if (arguments.length is 0) or (typeof arguments[0] is "boolean")
@getSharedObject().val(arguments[0])
else if arguments.length is 1
newXml = new @types.XmlType(undefined, undefined, undefined, undefined, arguments[0])
@HB.addOperation(newXml).execute()
@root_element.replace newXml
newXml
else
throw new Error "can only parse 0, or 1 parameter!"
#
# @see Operation.on
#
on: ()->
@getSharedObject().on arguments...
module.exports = XmlFramework
if window?
if not window.Y?
window.Y = {}
window.Y.XmlFramework = XmlFramework

View File

@ -277,16 +277,16 @@ module.exports = (HB)->
if o?
@deleted_by.push o
garbagecollect = false
if @prev_cl.isDeleted()
if not (@prev_cl? and @next_cl?) or @prev_cl.isDeleted()
garbagecollect = true
super garbagecollect
if @next_cl.isDeleted()
if @next_cl?.isDeleted()
# garbage collect next_cl
@next_cl.applyDelete()
cleanup: ()->
# TODO: Debugging
if @prev_cl.isDeleted()
if @prev_cl?.isDeleted()
# delete all ops that delete this insertion
for d in @deleted_by
d.cleanup()

View File

@ -257,8 +257,8 @@ module.exports = (HB)->
repl_manager.parent.callEvent 'change', property_name, op
# Call this, when the first element is inserted. Then delete the listener.
addPropertyListener = (event, op)->
repl_manager.parent.callEvent 'addProperty', property_name, op
repl_manager.deleteListener 'addProperty', addPropertyListener
repl_manager.parent.callEvent 'addProperty', property_name, op
@on 'insert', addPropertyListener
super parent

View File

@ -115,6 +115,22 @@ module.exports = (HB)->
cleanup: ()->
super()
push: (content)->
@insertAfter @end.prev_cl, content
insertAfter: (left, content)->
while left.isDeleted()
left = left.prev_cl # find the first character to the left, that is not deleted. Case position is 0, its the Delimiter.
right = left.next_cl
if content.type?
op = new TextInsert content, undefined, left, right
HB.addOperation(op).execute()
else
for c in content
op = new TextInsert c, undefined, left, right
HB.addOperation(op).execute()
left = op
@
#
# Inserts a string into the word.
#
@ -124,14 +140,7 @@ module.exports = (HB)->
# TODO: getOperationByPosition should return "(i-2)th" character
ith = @getOperationByPosition position # the (i-1)th character. e.g. "abc" a is the 0th character
left = ith.prev_cl # left is the non-deleted charather to the left of ith
while left.isDeleted()
left = left.prev_cl # find the first character to the left, that is not deleted. Case position is 0, its the Delimiter.
right = left.next_cl
for c in content
op = new TextInsert c, undefined, left, right
HB.addOperation(op).execute()
left = op
@
@insertAfter left, content
#
# Deletes a part of the word.

View File

@ -1,6 +1,16 @@
json_types_uninitialized = require "./JsonTypes"
Element?.prototype._proxy = (f_name, f)->
old_f = @[f_name]
if old_f?
@[f_name] = ()->
f.apply this, arguments
old_f.apply this, arguments
else
@[f_name] = f
module.exports = (HB)->
json_types = json_types_uninitialized HB
types = json_types.types
@ -11,8 +21,16 @@ module.exports = (HB)->
#
class XmlType extends types.Insert
constructor: (uid, @tagname, attributes, elements, prev_cl, next_cl, origin)->
super uid, prev_cl, next_cl, origin
constructor: (uid, @tagname, attributes, elements, @xml, prev, next, origin)->
if prev? and (not next?) and prev.type?
# adjust what you actually mean. you want to insert after prev, then
# next is not defined. but we only insert after non-deleted elements.
# This is also handled in TextInsert.
while prev.isDeleted()
prev = prev.prev_cl
next = prev.next_cl
super uid, prev, next, origin
if attributes? and elements?
@saveOperation 'attributes', attributes
@ -21,10 +39,31 @@ module.exports = (HB)->
@attributes = new types.JsonType()
HB.addOperation(@attributes).execute()
@elements = new types.WordType()
@elements.parent = @
HB.addOperation(@elements).execute()
else
throw new Error "Either define attribute and elements both, or none of them"
if @xml?
@tagname = @xml.tagName
for i in [0...@xml.attributes.length]
attr = xml.attributes[i]
@attributes.val(attr.name, attr.value)
for n in @xml.childNodes
if n.nodeType is n.TEXT_NODE
word = new types.WordType()
HB.addOperation(word).execute()
word.push n.textContent
@elements.push word
else if n.nodeType is n.ELEMENT_NODE
last = @elements.end
element = new XmlType undefined, undefined, undefined, undefined, n, last.prev_cl, last
HB.addOperation(element).execute()
@elements.push element
else
throw new Error "I don't know Node-type #{n.nodeType}!!"
@setXmlProxy()
undefined
#
# Identifies this class.
@ -40,28 +79,43 @@ module.exports = (HB)->
cleanup: ()->
super()
val: ()->
if document?
if arguments.length is 0
if not @xml?
@xml = document.createElement @tagname
attr = @attributes.val()
for attr_name, value of attr
a = document.createAttribute attr_name
a.value = value
@xml.setAttributeNode a
e = @elements.beginning.next_cl
while e.type isnt "Delimiter"
if not e.isDeleted()
@xml.appendChild e.val()
e.next_cl
@xml
else if arguments.length is 1
setXmlProxy: ()->
@xml._yatta = @
@xml._proxy 'insertBefore', (insertedNode, adjacentNode)->
next = adjacentNode?._yatta
prev = null
if next?
prev = next.prev_cl
else
throw new Error "Can only parse one parameter"
prev = @_yatta.elements.end.prev_cl
element = new XmlType undefined, undefined, undefined, undefined, insertedNode, prev
HB.addOperation(element).execute()
val: (enforce = false)->
if document?
if (not @xml?) or enforce
@xml = document.createElement @tagname
attr = @attributes.val()
for attr_name, value of attr
a = document.createAttribute attr_name
a.value = value
@xml.setAttributeNode a
e = @elements.beginning.next_cl
while e.type isnt "Delimiter"
if not e.isDeleted()
if e.type is "XmlType"
@xml.appendChild e.val(enforce)
else if e.type is "WordType"
text_node = document.createTextNode e.val()
@xml.appendChild text_node
else
throw new Error "Internal structure cannot be transformed to dom"
e = e.next_cl
@setXmlProxy()
@xml
#
@ -99,12 +153,11 @@ module.exports = (HB)->
'elements' : @elements.getUid()
'tagname' : @tagname
'uid' : @getUid()
'uid' : @getUid()
'prev': @prev_cl.getUid()
'next': @next_cl.getUid()
'prev': @prev_cl?.getUid()
'next': @next_cl?.getUid()
}
if @origin isnt @prev_cl
json["origin"] = @origin.getUid()
json["origin"] = @origin?.getUid()
json
parser['XmlType'] = (json)->
@ -117,7 +170,8 @@ module.exports = (HB)->
'next': next
'origin' : origin
} = json
new XmlType uid, tagname, attributes, elements, prev, next, origin
new XmlType uid, tagname, attributes, elements, undefined, prev, next, origin
types['XmlType'] = XmlType

View File

@ -8,4 +8,6 @@ exports['JsonFramework'] =
require './Frameworks/JsonFramework'
exports['TextFramework'] =
require './Frameworks/TextFramework'
exports['XmlFramework'] =
require './Frameworks/XmlFramework'

View File

@ -34,6 +34,7 @@
},
"devDependencies": {
"chai": "^1.9.1",
"codo": "^2.0.9",
"coffee-script": "^1.7.1",
"coffeeify": "^0.6.0",
"gulp": "^3.8.7",
@ -47,14 +48,15 @@
"gulp-ignore": "^1.2.0",
"gulp-ljs": "^0.1.1",
"gulp-mocha": "^0.5.2",
"gulp-mocha-phantomjs": "^0.5.0",
"gulp-rename": "^1.2.0",
"gulp-rimraf": "^0.1.0",
"gulp-run": "^1.6.3",
"gulp-sourcemaps": "^1.1.1",
"gulp-uglify": "^0.3.1",
"jquery": "^2.1.1",
"mocha": "^1.21.4",
"sinon": "^1.10.2",
"sinon-chai": "^2.5.0",
"codo": "^2.0.9"
"sinon-chai": "^2.5.0"
}
}

View File

@ -14,7 +14,7 @@ module.exports = class Test
constructor: (@name_suffix = "")->
@number_of_test_cases_multiplier = 1
@repeat_this = 1 * @number_of_test_cases_multiplier
@doSomething_amount = 800 * @number_of_test_cases_multiplier
@doSomething_amount = 20 + @number_of_test_cases_multiplier
@number_of_engines = 5 + @number_of_test_cases_multiplier - 1
@time = 0
@ -31,7 +31,7 @@ module.exports = class Test
for i in [0...@number_of_engines]
u = @makeNewUser (i+@name_suffix), @Connector
@users.push u
@users[0].val('name',"i")
#@users[0].val('name',"i")
@flushAll()
makeNewUser: (user)->

View File

@ -0,0 +1,49 @@
chai = require('chai')
expect = chai.expect
should = chai.should()
sinon = require('sinon')
sinonChai = require('sinon-chai')
_ = require("underscore")
$ = require("jquery")
document?.$ = $ # for browser
require 'coffee-errors'
chai.use(sinonChai)
Y = require "../lib/index"
Connector_uninitialized = require "../lib/Connectors/TestConnector"
Test = require "./TestSuite"
class XmlTest extends Test
type: "XmlTest"
makeNewUser: (user, conn)->
super new Y.XmlFramework user, conn
getRandomRoot: (user_num)->
@users[user_num].getSharedObject()
getContent: (user_num)->
@users[user_num].val()
describe "XmlFramework", ->
beforeEach (done)->
@timeout 50000
@yTest = new XmlTest()
###
@users = @yTest.users
###
@test_user = @yTest.makeNewUser 0, (Connector_uninitialized [])
done()
it "can transform to a real Dom element", ->
dom = $("#test_dom")[0]
@test_user.val(dom)
dom_ = @test_user.val(true)
expect(dom_ isnt dom).to.be.true
expect(dom_.outerHTML).to.equal(dom.outerHTML)
console.log "dtrn"