Cleaning up. No more bubbling events. All tests run fine. Following the Object.observe pattern (untested).
This commit is contained in:
parent
584964153c
commit
21f7350c4d
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"version":3,"sources":["ConnectorAdapter.coffee"],"names":[],"mappings":"AAOA;AAAA,MAAA,cAAA;;AAAA,EAAA,cAAA,GAAiB,SAAC,SAAD,EAAY,MAAZ,EAAoB,EAApB,EAAwB,kBAAxB,GAAA;AACf,QAAA,uCAAA;AAAA,IAAA,KAAA,GAAQ,SAAC,CAAD,GAAA;AACN,MAAA,IAAG,CAAC,CAAC,GAAG,CAAC,OAAN,KAAiB,EAAE,CAAC,SAAH,CAAA,CAAjB,IAAoC,CAAC,MAAA,CAAA,CAAQ,CAAC,GAAG,CAAC,SAAb,KAA4B,QAA7B,CAAvC;eACE,SAAS,CAAC,SAAV,CAAoB,CAApB,EADF;OADM;IAAA,CAAR,CAAA;AAAA,IAIA,kBAAkB,CAAC,IAAnB,CAAwB,KAAxB,CAJA,CAAA;AAAA,IAKA,eAAA,GAAkB,SAAA,GAAA;aAChB,EAAE,CAAC,mBAAH,CAAA,EADgB;IAAA,CALlB,CAAA;AAAA,IAOA,MAAA,GAAS,SAAC,YAAD,GAAA;aACP,EAAE,CAAC,OAAH,CAAW,YAAX,EADO;IAAA,CAPT,CAAA;AAAA,IASA,OAAA,GAAU,SAAC,EAAD,GAAA;aACR,MAAM,CAAC,mBAAP,CAA2B,EAA3B,EADQ;IAAA,CATV,CAAA;AAAA,IAWA,SAAS,CAAC,WAAV,CAAsB,eAAtB,EAAuC,MAAvC,EAA+C,OAA/C,CAXA,CAAA;WAaA,SAAS,CAAC,aAAV,CAAwB,SAAC,MAAD,EAAS,EAAT,GAAA;AACtB,MAAA,IAAG,EAAE,CAAC,GAAG,CAAC,OAAP,KAAoB,EAAE,CAAC,SAAH,CAAA,CAAvB;eACE,MAAM,CAAC,OAAP,CAAe,EAAf,EADF;OADsB;IAAA,CAAxB,EAde;EAAA,CAAjB,CAAA;;AAAA,EAkBA,MAAM,CAAC,OAAP,GAAiB,cAlBjB,CAAA;AAAA","file":"ConnectorAdapter.js","sourceRoot":"/source/","sourcesContent":["\n\n#\n# @param {Engine} engine The transformation engine\n# @param {HistoryBuffer} HB\n# @param {Array<Function>} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n#\nadaptConnector = (connector, engine, HB, execution_listener)->\n send_ = (o)->\n if o.uid.creator is HB.getUserId() and (typeof o.uid.op_number isnt \"string\")\n connector.broadcast o\n \n execution_listener.push send_\n sendStateVector = ()->\n HB.getOperationCounter()\n sendHb = (state_vector)->\n HB._encode(state_vector)\n applyHb = (hb)->\n engine.applyOpsCheckDouble hb\n connector.whenSyncing sendStateVector, sendHb, applyHb\n \n connector.whenReceiving (sender, op)->\n if op.uid.creator isnt HB.getUserId()\n engine.applyOp op\n \nmodule.exports = adaptConnector"]}
|
||||
{"version":3,"sources":["ConnectorAdapter.coffee"],"names":[],"mappings":"AAOA;AAAA,MAAA,cAAA;;AAAA,EAAA,cAAA,GAAiB,SAAC,SAAD,EAAY,MAAZ,EAAoB,EAApB,EAAwB,kBAAxB,GAAA;AACf,QAAA,uCAAA;AAAA,IAAA,KAAA,GAAQ,SAAC,CAAD,GAAA;AACN,MAAA,IAAG,CAAC,CAAC,GAAG,CAAC,OAAN,KAAiB,EAAE,CAAC,SAAH,CAAA,CAAjB,IAAoC,CAAC,MAAA,CAAA,CAAQ,CAAC,GAAG,CAAC,SAAb,KAA4B,QAA7B,CAAvC;eACE,SAAS,CAAC,SAAV,CAAoB,CAApB,EADF;OADM;IAAA,CAAR,CAAA;AAAA,IAIA,kBAAkB,CAAC,IAAnB,CAAwB,KAAxB,CAJA,CAAA;AAAA,IAKA,eAAA,GAAkB,SAAA,GAAA;aAChB,EAAE,CAAC,mBAAH,CAAA,EADgB;IAAA,CALlB,CAAA;AAAA,IAOA,MAAA,GAAS,SAAC,YAAD,GAAA;aACP,EAAE,CAAC,OAAH,CAAW,YAAX,EADO;IAAA,CAPT,CAAA;AAAA,IASA,OAAA,GAAU,SAAC,EAAD,GAAA;aACR,MAAM,CAAC,mBAAP,CAA2B,EAA3B,EADQ;IAAA,CATV,CAAA;AAAA,IAWA,SAAS,CAAC,WAAV,CAAsB,eAAtB,EAAuC,MAAvC,EAA+C,OAA/C,CAXA,CAAA;WAaA,SAAS,CAAC,aAAV,CAAwB,SAAC,MAAD,EAAS,EAAT,GAAA;AACtB,MAAA,IAAG,EAAE,CAAC,GAAG,CAAC,OAAP,KAAoB,EAAE,CAAC,SAAH,CAAA,CAAvB;eACE,MAAM,CAAC,OAAP,CAAe,EAAf,EADF;OADsB;IAAA,CAAxB,EAde;EAAA,CAAjB,CAAA;;AAAA,EAkBA,MAAM,CAAC,OAAP,GAAiB,cAlBjB,CAAA;AAAA","file":"ConnectorAdapter.js","sourceRoot":"/source/","sourcesContent":["\n\n#\n# @param {Engine} engine The transformation engine\n# @param {HistoryBuffer} HB\n# @param {Array<Function>} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n#\nadaptConnector = (connector, engine, HB, execution_listener)->\n send_ = (o)->\n if o.uid.creator is HB.getUserId() and (typeof o.uid.op_number isnt \"string\")\n connector.broadcast o\n\n execution_listener.push send_\n sendStateVector = ()->\n HB.getOperationCounter()\n sendHb = (state_vector)->\n HB._encode(state_vector)\n applyHb = (hb)->\n engine.applyOpsCheckDouble hb\n connector.whenSyncing sendStateVector, sendHb, applyHb\n\n connector.whenReceiving (sender, op)->\n if op.uid.creator isnt HB.getUserId()\n engine.applyOp op\n\nmodule.exports = adaptConnector"]}
|
@ -1,6 +1,18 @@
|
||||
(function() {
|
||||
var Engine;
|
||||
|
||||
if (typeof window !== "undefined" && window !== null) {
|
||||
window.unprocessed_counter = 0;
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined" && window !== null) {
|
||||
window.unprocessed_exec_counter = 0;
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined" && window !== null) {
|
||||
window.unprocessed_types = [];
|
||||
}
|
||||
|
||||
Engine = (function() {
|
||||
function Engine(HB, parser) {
|
||||
this.HB = HB;
|
||||
@ -66,6 +78,12 @@
|
||||
|
||||
} else if (!o.execute()) {
|
||||
this.unprocessed_ops.push(o);
|
||||
if (typeof window !== "undefined" && window !== null) {
|
||||
window.unprocessed_counter++;
|
||||
}
|
||||
if (typeof window !== "undefined" && window !== null) {
|
||||
window.unprocessed_types.push(o.type);
|
||||
}
|
||||
}
|
||||
return this.tryUnprocessed();
|
||||
};
|
||||
@ -74,6 +92,9 @@
|
||||
var old_length, op, unprocessed, _i, _len, _ref, _results;
|
||||
_results = [];
|
||||
while (true) {
|
||||
if (typeof window !== "undefined" && window !== null) {
|
||||
window.unprocessed_exec_counter++;
|
||||
}
|
||||
old_length = this.unprocessed_ops.length;
|
||||
unprocessed = [];
|
||||
_ref = this.unprocessed_ops;
|
||||
|
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
@ -178,7 +178,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -119,30 +119,6 @@ if (x.type === "JsonType") {
|
||||
Transform this to a Json.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#setReplaceManager-dynamic'>
|
||||
#
|
||||
(void)
|
||||
<b>setReplaceManager</b><span>(replace_manager)</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class='desc'>
|
||||
Sets the parent of this JsonType object.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#getParent-dynamic'>
|
||||
#
|
||||
(JsonType)
|
||||
<b>getParent</b><span>()</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class='desc'>
|
||||
Get the parent of this JsonType.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#setMutableDefault-dynamic'>
|
||||
@ -207,8 +183,9 @@ if (x.type === "JsonType") {
|
||||
<br>
|
||||
</p>
|
||||
<div class='docstring'>
|
||||
<p>Transform this to a Json. If your browser supports Object.observe it will be transformed automatically when a change arrives.
|
||||
Otherwise you will loose all the sharing-abilities (the new object will be a deep clone)!</p>
|
||||
<p>Transform this to a Json. If your browser supports Object.observe it will be transformed automatically when a change arrives.
|
||||
Otherwise you will loose all the sharing-abilities (the new object will be a deep clone)!</p><p>TODO: at the moment you don't consider changing of properties.
|
||||
E.g.: let x = {a:[]}. Then x.a.push 1 wouldn't change anything</p>
|
||||
</div>
|
||||
<div class='tags'>
|
||||
<h3>Returns:</h3>
|
||||
@ -218,45 +195,6 @@ Otherwise you will loose all the sharing-abilities (the new object will be a dee
|
||||
<tt>Json</tt>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class='method_details'>
|
||||
<p class='signature' id='setReplaceManager-dynamic'>
|
||||
#
|
||||
(void)
|
||||
<b>setReplaceManager</b><span>(replace_manager)</span>
|
||||
<br>
|
||||
</p>
|
||||
<div class='docstring'>
|
||||
<p>Sets the parent of this JsonType object.</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'>
|
||||
#
|
||||
(JsonType)
|
||||
<b>getParent</b><span>()</span>
|
||||
<br>
|
||||
</p>
|
||||
<div class='docstring'>
|
||||
<p>Get the parent of this JsonType.</p>
|
||||
</div>
|
||||
<div class='tags'>
|
||||
<h3>Returns:</h3>
|
||||
<ul class='return'>
|
||||
<li>
|
||||
<span class='type'></span>
|
||||
<tt><a href='../class/JsonType.html'>JsonType</a></tt>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class='method_details'>
|
||||
@ -421,7 +359,7 @@ Otherwise you will loose all the sharing-abilities (the new object will be a dee
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -139,7 +139,7 @@ console.log(w.newProperty == "Awesome") # true!</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -145,18 +145,6 @@ if (x.type === "WordType") {
|
||||
Deletes a part of the word.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#replaceText-dynamic'>
|
||||
#
|
||||
(WordType)
|
||||
<b>replaceText</b><span>(text)</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class='desc'>
|
||||
Replace the content of this word with another one.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#val-dynamic'>
|
||||
@ -181,20 +169,6 @@ if (x.type === "WordType") {
|
||||
Same as WordType.val
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#setReplaceManager-dynamic'>
|
||||
#
|
||||
(void)
|
||||
<b>setReplaceManager</b><span>(op)</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class='note private title'>Private</span>
|
||||
<span class='desc'>
|
||||
In most cases you would embed a WordType in a Replaceable, wich is handled by the ReplaceManager in order to provide replace functionality.
|
||||
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#bind-dynamic'>
|
||||
@ -332,31 +306,6 @@ if (x.type === "WordType") {
|
||||
<span class='desc'>This WordType object </span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class='method_details'>
|
||||
<p class='signature' id='replaceText-dynamic'>
|
||||
#
|
||||
(WordType)
|
||||
<b>replaceText</b><span>(text)</span>
|
||||
<br>
|
||||
</p>
|
||||
<div class='docstring'>
|
||||
<p>Replace the content of this word with another one. Concurrent replacements are not merged!
|
||||
Only one of the replacements will be used.</p>
|
||||
</div>
|
||||
<div class='tags'>
|
||||
<h3>Returns:</h3>
|
||||
<ul class='return'>
|
||||
<li>
|
||||
<span class='type'></span>
|
||||
(
|
||||
<tt><a href='../class/WordType.html'>WordType</a></tt>
|
||||
)
|
||||
—
|
||||
<span class='desc'>Returns the new WordType object. </span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class='method_details'>
|
||||
@ -400,21 +349,6 @@ Only one of the replacements will be used.</p>
|
||||
<a href='WordType.val'>WordType.val</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class='method_details'>
|
||||
<p class='signature' id='setReplaceManager-dynamic'>
|
||||
#
|
||||
(void)
|
||||
<b>setReplaceManager</b><span>(op)</span>
|
||||
<span class='note private'>Private</span>
|
||||
<br>
|
||||
</p>
|
||||
<div class='docstring'>
|
||||
<p>In most cases you would embed a WordType in a Replaceable, wich is handled by the ReplaceManager in order
|
||||
to provide replace functionality.</p>
|
||||
</div>
|
||||
<div class='tags'>
|
||||
</div>
|
||||
</div>
|
||||
<div class='method_details'>
|
||||
@ -455,7 +389,7 @@ yatta.bind(textbox);</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -128,10 +128,10 @@ Known values that are supported:</p><ul>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#on-dynamic'>
|
||||
<a href='#observe-dynamic'>
|
||||
#
|
||||
(void)
|
||||
<b>on</b><span>()</span>
|
||||
<b>observe</b><span>()</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class='desc'>
|
||||
@ -139,10 +139,10 @@ Known values that are supported:</p><ul>
|
||||
</li>
|
||||
<li>
|
||||
<span class='signature'>
|
||||
<a href='#deleteListener-dynamic'>
|
||||
<a href='#unobserve-dynamic'>
|
||||
#
|
||||
(void)
|
||||
<b>deleteListener</b><span>()</span>
|
||||
<b>unobserve</b><span>()</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class='desc'>
|
||||
@ -301,10 +301,10 @@ Yatta was initialized (Depending on the HistoryBuffer implementation).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class='method_details'>
|
||||
<p class='signature' id='on-dynamic'>
|
||||
<p class='signature' id='observe-dynamic'>
|
||||
#
|
||||
(void)
|
||||
<b>on</b><span>()</span>
|
||||
<b>observe</b><span>()</span>
|
||||
<br>
|
||||
</p>
|
||||
<div class='tags'>
|
||||
@ -317,10 +317,10 @@ Yatta was initialized (Depending on the HistoryBuffer implementation).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class='method_details'>
|
||||
<p class='signature' id='deleteListener-dynamic'>
|
||||
<p class='signature' id='unobserve-dynamic'>
|
||||
#
|
||||
(void)
|
||||
<b>deleteListener</b><span>()</span>
|
||||
<b>unobserve</b><span>()</span>
|
||||
<br>
|
||||
</p>
|
||||
<div class='tags'>
|
||||
@ -335,7 +335,7 @@ Yatta was initialized (Depending on the HistoryBuffer implementation).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -38,7 +38,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -76,7 +76,7 @@ But I would become really motivated if you gave me some feedback :) (<a href="ht
|
||||
</ul>
|
||||
<h2 id="support">Support</h2><p>Please report <em>any</em> issues to the <a href="https://github.com/DadaMonad/Yatta/issues">Github issue page</a>!
|
||||
I would appreciate if developers gave me feedback on how <em>convenient</em> the framework is, and if it is easy to use. Particularly the XML-support may not support every DOM-methods - if you encounter a method that does not cause any change on other peers,
|
||||
please state function name, and sample parameters. However, there are browser-specific features, that Yatta won't support.</p><h2 id="license">License</h2><p>Yatta! is licensed under the <a href="./LICENSE.txt">MIT License</a>.</p><a href="mailto:kevin.jahns@rwth-aachen.de">kevin.jahns@rwth-aachen.de</a>
|
||||
please state function name, and sample parameters. However, there are browser-specific features, that Yatta won't support.</p><h2 id="license">License</h2><p>Yatta! is licensed under the <a href="./LICENSE.txt">MIT License</a>.</p><a href="mailto:kevin.jahns@rwth-aachen.de">kevin.jahns@rwth-aachen.de</a>
|
||||
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@ please state function name, and sample parameters. However, there are browser-sp
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -106,7 +106,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -37,6 +37,30 @@
|
||||
</table>
|
||||
<h2>Variables Summary</h2>
|
||||
<dl class='constants'>
|
||||
<dt id='window.unprocessed_counter-variable'>
|
||||
window.unprocessed_counter
|
||||
=
|
||||
</dt>
|
||||
<dd>
|
||||
<pre><code class='coffeescript'>0</code></pre>
|
||||
|
||||
</dd>
|
||||
<dt id='window.unprocessed_exec_counter-variable'>
|
||||
window.unprocessed_exec_counter
|
||||
=
|
||||
</dt>
|
||||
<dd>
|
||||
<pre><code class='coffeescript'>0</code></pre>
|
||||
|
||||
</dd>
|
||||
<dt id='window.unprocessed_types-variable'>
|
||||
window.unprocessed_types
|
||||
=
|
||||
</dt>
|
||||
<dd>
|
||||
<pre><code class='coffeescript'>[]</code></pre>
|
||||
|
||||
</dd>
|
||||
<dt id='module.exports-variable'>
|
||||
module.exports
|
||||
=
|
||||
@ -48,7 +72,7 @@
|
||||
</dl>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -48,7 +48,7 @@
|
||||
</dl>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -39,7 +39,7 @@
|
||||
</table>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -39,7 +39,7 @@
|
||||
</table>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -39,7 +39,7 @@
|
||||
</table>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -39,7 +39,7 @@
|
||||
</table>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -58,7 +58,7 @@
|
||||
</dl>
|
||||
</div>
|
||||
<div id='footer'>
|
||||
December 16, 14 17:57:44 by
|
||||
December 17, 14 22:46:39 by
|
||||
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
|
||||
Codo
|
||||
</a>
|
||||
|
@ -1 +1 @@
|
||||
window.searchData = [{"t":"JsonTypeWrapper","p":"class/JsonTypeWrapper.html"},{"t":"JsonType","p":"class/JsonType.html"},{"t":"WordType","p":"class/WordType.html"},{"t":"Yatta","p":"class/Yatta.html"},{"t":"lib/ConnectorAdapter.coffee","p":"file/lib/ConnectorAdapter.coffee.html"},{"t":"lib/Engine.coffee","p":"file/lib/Engine.coffee.html"},{"t":"lib/HistoryBuffer.coffee","p":"file/lib/HistoryBuffer.coffee.html"},{"t":"lib/Types/BasicTypes.coffee","p":"file/lib/Types/BasicTypes.coffee.html"},{"t":"lib/Types/JsonTypes.coffee","p":"file/lib/Types/JsonTypes.coffee.html"},{"t":"lib/Types/StructuredTypes.coffee","p":"file/lib/Types/StructuredTypes.coffee.html"},{"t":"lib/Types/TextTypes.coffee","p":"file/lib/Types/TextTypes.coffee.html"},{"t":"lib/Yatta.coffee","p":"file/lib/Yatta.coffee.html"},{"t":"README.md","p":"extra/README.md.html"},{"t":"LICENSE.txt","p":"extra/LICENSE.txt.html"},{"t":"JsonType#_encode","p":"class/JsonType.html#_encode-dynamic"},{"t":"WordType#_encode","p":"class/WordType.html#_encode-dynamic"},{"t":"lib/ConnectorAdapter.coffee~adaptConnector","p":"file/lib/ConnectorAdapter.coffee.html#adaptConnector-"},{"t":"JsonType#applyDelete","p":"class/JsonType.html#applyDelete-dynamic"},{"t":"WordType#applyDelete","p":"class/WordType.html#applyDelete-dynamic"},{"t":"WordType#bind","p":"class/WordType.html#bind-dynamic"},{"t":"WordType#cleanup","p":"class/WordType.html#cleanup-dynamic"},{"t":"JsonType#cleanup","p":"class/JsonType.html#cleanup-dynamic"},{"t":"Yatta#constructor","p":"class/Yatta.html#constructor-dynamic"},{"t":"JsonTypeWrapper#constructor","p":"class/JsonTypeWrapper.html#constructor-dynamic"},{"t":"WordType#constructor","p":"class/WordType.html#constructor-dynamic"},{"t":"Yatta#deleteListener","p":"class/Yatta.html#deleteListener-dynamic"},{"t":"WordType#deleteText","p":"class/WordType.html#deleteText-dynamic"},{"t":"Yatta#getConnector","p":"class/Yatta.html#getConnector-dynamic"},{"t":"Yatta#getHistoryBuffer","p":"class/Yatta.html#getHistoryBuffer-dynamic"},{"t":"JsonType#getParent","p":"class/JsonType.html#getParent-dynamic"},{"t":"Yatta#getSharedObject","p":"class/Yatta.html#getSharedObject-dynamic"},{"t":"Yatta#getUserId","p":"class/Yatta.html#getUserId-dynamic"},{"t":"WordType#insertAfter","p":"class/WordType.html#insertAfter-dynamic"},{"t":"WordType#insertText","p":"class/WordType.html#insertText-dynamic"},{"t":"Yatta#on","p":"class/Yatta.html#on-dynamic"},{"t":"WordType#push","p":"class/WordType.html#push-dynamic"},{"t":"WordType#replaceText","p":"class/WordType.html#replaceText-dynamic"},{"t":"JsonType#setMutableDefault","p":"class/JsonType.html#setMutableDefault-dynamic"},{"t":"Yatta#setMutableDefault","p":"class/Yatta.html#setMutableDefault-dynamic"},{"t":"JsonType#setReplaceManager","p":"class/JsonType.html#setReplaceManager-dynamic"},{"t":"WordType#setReplaceManager","p":"class/WordType.html#setReplaceManager-dynamic"},{"t":"JsonType#toJson","p":"class/JsonType.html#toJson-dynamic"},{"t":"Yatta#toJson","p":"class/Yatta.html#toJson-dynamic"},{"t":"WordType#toString","p":"class/WordType.html#toString-dynamic"},{"t":"Yatta#val","p":"class/Yatta.html#val-dynamic"},{"t":"WordType#val","p":"class/WordType.html#val-dynamic"},{"t":"JsonType#val","p":"class/JsonType.html#val-dynamic"}]
|
||||
window.searchData = [{"t":"JsonTypeWrapper","p":"class/JsonTypeWrapper.html"},{"t":"JsonType","p":"class/JsonType.html"},{"t":"WordType","p":"class/WordType.html"},{"t":"Yatta","p":"class/Yatta.html"},{"t":"lib/ConnectorAdapter.coffee","p":"file/lib/ConnectorAdapter.coffee.html"},{"t":"lib/Engine.coffee","p":"file/lib/Engine.coffee.html"},{"t":"lib/HistoryBuffer.coffee","p":"file/lib/HistoryBuffer.coffee.html"},{"t":"lib/Types/BasicTypes.coffee","p":"file/lib/Types/BasicTypes.coffee.html"},{"t":"lib/Types/JsonTypes.coffee","p":"file/lib/Types/JsonTypes.coffee.html"},{"t":"lib/Types/StructuredTypes.coffee","p":"file/lib/Types/StructuredTypes.coffee.html"},{"t":"lib/Types/TextTypes.coffee","p":"file/lib/Types/TextTypes.coffee.html"},{"t":"lib/Yatta.coffee","p":"file/lib/Yatta.coffee.html"},{"t":"README.md","p":"extra/README.md.html"},{"t":"LICENSE.txt","p":"extra/LICENSE.txt.html"},{"t":"JsonType#_encode","p":"class/JsonType.html#_encode-dynamic"},{"t":"WordType#_encode","p":"class/WordType.html#_encode-dynamic"},{"t":"lib/ConnectorAdapter.coffee~adaptConnector","p":"file/lib/ConnectorAdapter.coffee.html#adaptConnector-"},{"t":"WordType#applyDelete","p":"class/WordType.html#applyDelete-dynamic"},{"t":"JsonType#applyDelete","p":"class/JsonType.html#applyDelete-dynamic"},{"t":"WordType#bind","p":"class/WordType.html#bind-dynamic"},{"t":"JsonType#cleanup","p":"class/JsonType.html#cleanup-dynamic"},{"t":"WordType#cleanup","p":"class/WordType.html#cleanup-dynamic"},{"t":"Yatta#constructor","p":"class/Yatta.html#constructor-dynamic"},{"t":"WordType#constructor","p":"class/WordType.html#constructor-dynamic"},{"t":"JsonTypeWrapper#constructor","p":"class/JsonTypeWrapper.html#constructor-dynamic"},{"t":"WordType#deleteText","p":"class/WordType.html#deleteText-dynamic"},{"t":"Yatta#getConnector","p":"class/Yatta.html#getConnector-dynamic"},{"t":"Yatta#getHistoryBuffer","p":"class/Yatta.html#getHistoryBuffer-dynamic"},{"t":"Yatta#getSharedObject","p":"class/Yatta.html#getSharedObject-dynamic"},{"t":"Yatta#getUserId","p":"class/Yatta.html#getUserId-dynamic"},{"t":"WordType#insertAfter","p":"class/WordType.html#insertAfter-dynamic"},{"t":"WordType#insertText","p":"class/WordType.html#insertText-dynamic"},{"t":"Yatta#observe","p":"class/Yatta.html#observe-dynamic"},{"t":"WordType#push","p":"class/WordType.html#push-dynamic"},{"t":"Yatta#setMutableDefault","p":"class/Yatta.html#setMutableDefault-dynamic"},{"t":"JsonType#setMutableDefault","p":"class/JsonType.html#setMutableDefault-dynamic"},{"t":"JsonType#toJson","p":"class/JsonType.html#toJson-dynamic"},{"t":"Yatta#toJson","p":"class/Yatta.html#toJson-dynamic"},{"t":"WordType#toString","p":"class/WordType.html#toString-dynamic"},{"t":"Yatta#unobserve","p":"class/Yatta.html#unobserve-dynamic"},{"t":"Yatta#val","p":"class/Yatta.html#val-dynamic"},{"t":"WordType#val","p":"class/WordType.html#val-dynamic"},{"t":"JsonType#val","p":"class/JsonType.html#val-dynamic"}]
|
@ -53,14 +53,6 @@
|
||||
(lib/ConnectorAdapter.coffee)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/JsonType.html#applyDelete-dynamic' target='main' title='applyDelete'>
|
||||
#applyDelete
|
||||
</a>
|
||||
<small>
|
||||
(JsonType)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/WordType.html#applyDelete-dynamic' target='main' title='applyDelete'>
|
||||
#applyDelete
|
||||
@ -70,16 +62,16 @@
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/WordType.html#bind-dynamic' target='main' title='bind'>
|
||||
#bind
|
||||
<a href='class/JsonType.html#applyDelete-dynamic' target='main' title='applyDelete'>
|
||||
#applyDelete
|
||||
</a>
|
||||
<small>
|
||||
(WordType)
|
||||
(JsonType)
|
||||
</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)
|
||||
@ -93,6 +85,14 @@
|
||||
(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/Yatta.html#constructor-dynamic' target='main' title='constructor'>
|
||||
#constructor
|
||||
@ -101,14 +101,6 @@
|
||||
(Yatta)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/JsonTypeWrapper.html#constructor-dynamic' target='main' title='constructor'>
|
||||
#constructor
|
||||
</a>
|
||||
<small>
|
||||
(JsonTypeWrapper)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/WordType.html#constructor-dynamic' target='main' title='constructor'>
|
||||
#constructor
|
||||
@ -118,11 +110,11 @@
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/Yatta.html#deleteListener-dynamic' target='main' title='deleteListener'>
|
||||
#deleteListener
|
||||
<a href='class/JsonTypeWrapper.html#constructor-dynamic' target='main' title='constructor'>
|
||||
#constructor
|
||||
</a>
|
||||
<small>
|
||||
(Yatta)
|
||||
(JsonTypeWrapper)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
@ -149,14 +141,6 @@
|
||||
(Yatta)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/JsonType.html#getParent-dynamic' target='main' title='getParent'>
|
||||
#getParent
|
||||
</a>
|
||||
<small>
|
||||
(JsonType)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/Yatta.html#getSharedObject-dynamic' target='main' title='getSharedObject'>
|
||||
#getSharedObject
|
||||
@ -190,8 +174,8 @@
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/Yatta.html#on-dynamic' target='main' title='on'>
|
||||
#on
|
||||
<a href='class/Yatta.html#observe-dynamic' target='main' title='observe'>
|
||||
#observe
|
||||
</a>
|
||||
<small>
|
||||
(Yatta)
|
||||
@ -205,22 +189,6 @@
|
||||
(WordType)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/WordType.html#replaceText-dynamic' target='main' title='replaceText'>
|
||||
#replaceText
|
||||
</a>
|
||||
<small>
|
||||
(WordType)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/JsonType.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
|
||||
#setMutableDefault
|
||||
</a>
|
||||
<small>
|
||||
(JsonType)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/Yatta.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
|
||||
#setMutableDefault
|
||||
@ -230,21 +198,13 @@
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/JsonType.html#setReplaceManager-dynamic' target='main' title='setReplaceManager'>
|
||||
#setReplaceManager
|
||||
<a href='class/JsonType.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
|
||||
#setMutableDefault
|
||||
</a>
|
||||
<small>
|
||||
(JsonType)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/WordType.html#setReplaceManager-dynamic' target='main' title='setReplaceManager'>
|
||||
#setReplaceManager
|
||||
</a>
|
||||
<small>
|
||||
(WordType)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/JsonType.html#toJson-dynamic' target='main' title='toJson'>
|
||||
#toJson
|
||||
@ -269,6 +229,14 @@
|
||||
(WordType)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/Yatta.html#unobserve-dynamic' target='main' title='unobserve'>
|
||||
#unobserve
|
||||
</a>
|
||||
<small>
|
||||
(Yatta)
|
||||
</small>
|
||||
</li>
|
||||
<li>
|
||||
<a href='class/Yatta.html#val-dynamic' target='main' title='val'>
|
||||
#val
|
||||
|
@ -0,0 +1,31 @@
|
||||
## IWC + JSON Example
|
||||
Here, I will give a short overview on how to use the IwcJson Framework in Role-SDK widgets.
|
||||
First you have to include the following libraries in your widget file:
|
||||
```
|
||||
<script src="http://open-app.googlecode.com/files/openapp.js"></script>
|
||||
<script src="http://dbis.rwth-aachen.de/gadgets/iwc/lib/iwc.js"></script>
|
||||
<script src="http://dbis.rwth-aachen.de/~jahns/role-widgets/widgetbundles/libraries/DUIClient.js"></script>
|
||||
<script src="../../build/browser/Frameworks/JsonFramework.min.js"></script>
|
||||
<script src="../../build/browser/Connectors/IwcConnector.min.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
```
|
||||
A working widget implementation is [IwcJson.xml](./IwcJson.xml) and the js-file is [index.js](./index.js)
|
||||
|
||||
|
||||
```js
|
||||
function init(){
|
||||
Y.createIwcConnector(function(Connector, user_id){
|
||||
```
|
||||
|
||||
|
||||
You don't have to use the proposed user_id.
|
||||
|
||||
|
||||
```js
|
||||
console.log("me is number 2")
|
||||
yatta = new Y.JsonYatta(2, Connector);
|
||||
|
||||
})
|
||||
}
|
||||
window.onload = init
|
||||
```
|
@ -9,7 +9,7 @@ adaptConnector = (connector, engine, HB, execution_listener)->
|
||||
send_ = (o)->
|
||||
if o.uid.creator is HB.getUserId() and (typeof o.uid.op_number isnt "string")
|
||||
connector.broadcast o
|
||||
|
||||
|
||||
execution_listener.push send_
|
||||
sendStateVector = ()->
|
||||
HB.getOperationCounter()
|
||||
@ -18,9 +18,9 @@ adaptConnector = (connector, engine, HB, execution_listener)->
|
||||
applyHb = (hb)->
|
||||
engine.applyOpsCheckDouble hb
|
||||
connector.whenSyncing sendStateVector, sendHb, applyHb
|
||||
|
||||
|
||||
connector.whenReceiving (sender, op)->
|
||||
if op.uid.creator isnt HB.getUserId()
|
||||
engine.applyOp op
|
||||
|
||||
|
||||
module.exports = adaptConnector
|
@ -1,4 +1,8 @@
|
||||
|
||||
window?.unprocessed_counter = 0 # del this
|
||||
window?.unprocessed_exec_counter = 0 # TODO
|
||||
window?.unprocessed_types = []
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# The Engine handles how and in which order to execute operations and add operations to the HistoryBuffer.
|
||||
@ -22,7 +26,7 @@ class Engine
|
||||
else
|
||||
throw new Error "You forgot to specify a parser for type #{json.type}. The message is #{JSON.stringify json}."
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Apply a set of operations. E.g. the operations you received from another users HB._encode().
|
||||
# @note You must not use this method when you already have ops in your HB!
|
||||
@ -63,6 +67,8 @@ class Engine
|
||||
if @HB.getOperation(o)?
|
||||
else if not o.execute()
|
||||
@unprocessed_ops.push o
|
||||
window?.unprocessed_counter++ # TODO: del this
|
||||
window?.unprocessed_types.push o.type
|
||||
@tryUnprocessed()
|
||||
|
||||
#
|
||||
@ -71,6 +77,7 @@ class Engine
|
||||
#
|
||||
tryUnprocessed: ()->
|
||||
while true
|
||||
window?.unprocessed_exec_counter++ # TODO: del this
|
||||
old_length = @unprocessed_ops.length
|
||||
unprocessed = []
|
||||
for op in @unprocessed_ops
|
||||
|
@ -134,7 +134,7 @@ class HistoryBuffer
|
||||
#
|
||||
# Retrieve an operation from a unique id.
|
||||
#
|
||||
getOperation: (uid)->
|
||||
getOperation: (uid)->
|
||||
if uid.uid?
|
||||
uid = uid.uid
|
||||
@buffer[uid.creator]?[uid.op_number]
|
||||
|
@ -19,12 +19,13 @@ module.exports = (HB)->
|
||||
class Operation
|
||||
|
||||
#
|
||||
# @param {Object} uid A unique identifier.
|
||||
# @param {Object} uid A unique identifier.
|
||||
# If uid is undefined, a new uid will be created before at the end of the execution sequence
|
||||
#
|
||||
constructor: (uid)->
|
||||
@is_deleted = false
|
||||
@garbage_collected = false
|
||||
@event_listeners = [] # TODO: rename to observers or sth like that
|
||||
if uid?
|
||||
@uid = uid
|
||||
|
||||
@ -32,41 +33,27 @@ module.exports = (HB)->
|
||||
|
||||
#
|
||||
# Add an event listener. It depends on the operation which events are supported.
|
||||
# @param {String} event Name of the event.
|
||||
# @param {Function} f f is executed in case the event fires.
|
||||
#
|
||||
on: (events, f)->
|
||||
@event_listeners ?= {}
|
||||
if events.constructor isnt [].constructor
|
||||
events = [events]
|
||||
for e in events
|
||||
@event_listeners[e] ?= []
|
||||
@event_listeners[e].push f
|
||||
observe: (f)->
|
||||
@event_listeners.push f
|
||||
|
||||
#
|
||||
# Deletes a function from an event / list of events.
|
||||
# @see Operation.on
|
||||
# Deletes function from the observer list
|
||||
# @see Operation.observe
|
||||
#
|
||||
# @overload deleteListener(event, f)
|
||||
# @param event {String} An event name
|
||||
# @param f {Function} The function that you want to delete from these events
|
||||
# @overload deleteListener(events, f)
|
||||
# @param events {Array<String>} A list of event names
|
||||
# @param f {Function} The function that you want to delete from these events.
|
||||
deleteListener: (events, f)->
|
||||
if events.constructor isnt [].constructor
|
||||
events = [events]
|
||||
for e in events
|
||||
if @event_listeners?[e]?
|
||||
@event_listeners[e] = @event_listeners[e].filter (g)->
|
||||
f isnt g
|
||||
|
||||
#
|
||||
# Deletes all subscribed event listeners.
|
||||
# This should be called, e.g. after this has been replaced.
|
||||
# @overload unobserve(event, f)
|
||||
# @param f {Function} The function that you want to delete
|
||||
unobserve: (f)->
|
||||
@event_listeners.filter (g)->
|
||||
f isnt g
|
||||
|
||||
#
|
||||
# Deletes all subscribed event listeners.
|
||||
# This should be called, e.g. after this has been replaced.
|
||||
# (Then only one replace event should fire. )
|
||||
# This is also called in the cleanup method.
|
||||
deleteAllListeners: ()->
|
||||
# This is also called in the cleanup method.
|
||||
deleteAllObservers: ()->
|
||||
@event_listeners = []
|
||||
|
||||
#
|
||||
@ -78,11 +65,10 @@ module.exports = (HB)->
|
||||
|
||||
#
|
||||
# Fire an event and specify in which context the listener is called (set 'this').
|
||||
#
|
||||
forwardEvent: (op, event, args...)->
|
||||
if @event_listeners?[event]?
|
||||
for f in @event_listeners[event]
|
||||
f.call op, event, args...
|
||||
# TODO: do you need this ?
|
||||
forwardEvent: (op, args...)->
|
||||
for f in @event_listeners
|
||||
f.call op, args...
|
||||
|
||||
isDeleted: ()->
|
||||
@is_deleted
|
||||
@ -98,7 +84,7 @@ module.exports = (HB)->
|
||||
cleanup: ()->
|
||||
#console.log "cleanup: #{@type}"
|
||||
HB.removeOperation @
|
||||
@deleteAllListeners()
|
||||
@deleteAllObservers()
|
||||
|
||||
#
|
||||
# Set the parent of this operation.
|
||||
@ -128,15 +114,15 @@ module.exports = (HB)->
|
||||
#
|
||||
execute: ()->
|
||||
@is_executed = true
|
||||
if not @uid?
|
||||
# When this operation was created without a uid, then set it here.
|
||||
# There is only one other place, where this can be done - before an Insertion
|
||||
if not @uid?
|
||||
# When this operation was created without a uid, then set it here.
|
||||
# There is only one other place, where this can be done - before an Insertion
|
||||
# is executed (because we need the creator_id)
|
||||
@uid = HB.getNextOperationIdentifier()
|
||||
@uid = HB.getNextOperationIdentifier()
|
||||
HB.addOperation @
|
||||
for l in execution_listener
|
||||
l @_encode()
|
||||
@
|
||||
@
|
||||
|
||||
#
|
||||
# @private
|
||||
@ -388,7 +374,7 @@ module.exports = (HB)->
|
||||
if parent? and fire_event
|
||||
@setParent parent
|
||||
@parent.callEvent "insert", @
|
||||
@
|
||||
@
|
||||
|
||||
#
|
||||
# Compute the position of this operation.
|
||||
@ -501,7 +487,7 @@ module.exports = (HB)->
|
||||
delete @prev_cl.unchecked.next_cl
|
||||
@prev_cl.next_cl = @
|
||||
super
|
||||
else if @prev_cl? or @next_cl? or true # TODO: are you sure? This can happen right?
|
||||
else if @prev_cl? or @next_cl? or true # TODO: are you sure? This can happen right?
|
||||
super
|
||||
#else
|
||||
# throw new Error "Delimiter is unsufficient defined!"
|
||||
|
@ -115,12 +115,16 @@ module.exports = (HB)->
|
||||
|
||||
cleanup: ()->
|
||||
super()
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Transform this to a Json. If your browser supports Object.observe it will be transformed automatically when a change arrives.
|
||||
# Transform this to a Json. If your browser supports Object.observe it will be transformed automatically when a change arrives.
|
||||
# Otherwise you will loose all the sharing-abilities (the new object will be a deep clone)!
|
||||
# @return {Json}
|
||||
#
|
||||
# TODO: at the moment you don't consider changing of properties.
|
||||
# E.g.: let x = {a:[]}. Then x.a.push 1 wouldn't change anything
|
||||
#
|
||||
toJson: ()->
|
||||
if not @bound_json? or not Object.observe? or true # TODO: currently, you are not watching mutable strings for changes, and, therefore, the @bound_json is not updated. TODO TODO wuawuawua easy
|
||||
val = @val()
|
||||
@ -137,14 +141,14 @@ module.exports = (HB)->
|
||||
else
|
||||
json[name] = o
|
||||
@bound_json = json
|
||||
if Object.observe?
|
||||
if Object.observe?
|
||||
that = @
|
||||
Object.observe @bound_json, (events)->
|
||||
for event in events
|
||||
if not event.changed_by? and (event.type is "add" or event.type = "update")
|
||||
# this event is not created by Yatta.
|
||||
that.val(event.name, event.object[event.name])
|
||||
that.on 'change', (event_name, property_name, op)->
|
||||
that.observe (event_name, property_name, op)->
|
||||
if this is that and op.uid.creator isnt HB.getUserId()
|
||||
notifier = Object.getNotifier(that.bound_json)
|
||||
oldVal = that.bound_json[property_name]
|
||||
@ -152,17 +156,17 @@ module.exports = (HB)->
|
||||
notifier.performChange 'update', ()->
|
||||
that.bound_json[property_name] = that.val(property_name)
|
||||
, that.bound_json
|
||||
notifier.notify
|
||||
notifier.notify
|
||||
object: that.bound_json
|
||||
type: 'update'
|
||||
name: property_name
|
||||
oldValue: oldVal
|
||||
changed_by: op.uid.creator
|
||||
else
|
||||
else
|
||||
notifier.performChange 'add', ()->
|
||||
that.bound_json[property_name] = that.val(property_name)
|
||||
, that.bound_json
|
||||
notifier.notify
|
||||
notifier.notify
|
||||
object: that.bound_json
|
||||
type: 'add'
|
||||
name: property_name
|
||||
@ -170,23 +174,6 @@ module.exports = (HB)->
|
||||
changed_by: op.uid.creator
|
||||
@bound_json
|
||||
|
||||
#
|
||||
# @see WordType.setReplaceManager
|
||||
# Sets the parent of this JsonType object.
|
||||
#
|
||||
setReplaceManager: (replace_manager)->
|
||||
@replace_manager = replace_manager
|
||||
@on ['change','addProperty'], ()->
|
||||
if replace_manager.parent?
|
||||
replace_manager.parent.forwardEvent this, arguments...
|
||||
|
||||
#
|
||||
# Get the parent of this JsonType.
|
||||
# @return {JsonType}
|
||||
#
|
||||
getParent: ()->
|
||||
@replace_manager.parent
|
||||
|
||||
#
|
||||
# Whether the default is 'mutable' (true) or 'immutable' (false)
|
||||
#
|
||||
@ -222,16 +209,7 @@ module.exports = (HB)->
|
||||
# @return [JsonType] This object. (supports chaining)
|
||||
#
|
||||
val: (name, content, mutable)->
|
||||
if typeof name is 'object'
|
||||
# Special case. First argument is an object. Then the second arg is mutable.
|
||||
# (I refer to var name and content here)
|
||||
# Keep that in mind when reading the following..
|
||||
jt = new JsonType()
|
||||
@replace_manager.replace jt.execute()
|
||||
for n,o of name
|
||||
jt.val n, o, mutable
|
||||
@
|
||||
else if name? and arguments.length > 1
|
||||
if name? and arguments.length > 1
|
||||
if mutable?
|
||||
if mutable is true or mutable is 'mutable'
|
||||
mutable = true
|
||||
|
@ -91,10 +91,10 @@ module.exports = (HB)->
|
||||
# always have the same result (ReplaceManager, and its beginning and end are the same)
|
||||
#
|
||||
execute: ()->
|
||||
if not @validateSavedOperations()
|
||||
if not @validateSavedOperations()
|
||||
return false
|
||||
else
|
||||
# helper for cloning an object
|
||||
# helper for cloning an object
|
||||
clone = (o)->
|
||||
p = {}
|
||||
for name,value of o
|
||||
@ -110,7 +110,7 @@ module.exports = (HB)->
|
||||
uid_end.op_number = "#{uid_r.op_number}_end"
|
||||
beg = (new types.Delimiter uid_beg, undefined, uid_end).execute()
|
||||
end = (new types.Delimiter uid_end, beg, undefined).execute()
|
||||
@map_manager.map[@name] = new ReplaceManager undefined, uid_r, beg, end
|
||||
@map_manager.map[@name] = new ReplaceManager uid_r, beg, end
|
||||
@map_manager.map[@name].setParent @map_manager, @name
|
||||
(@map_manager.map[@name].add_name_ops ?= []).push @
|
||||
@map_manager.map[@name].execute()
|
||||
@ -224,10 +224,8 @@ module.exports = (HB)->
|
||||
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||
# @param {Delimiter} beginning Reference or Object.
|
||||
# @param {Delimiter} end Reference or Object.
|
||||
constructor: (initial_content, uid, beginning, end, prev, next, origin)->
|
||||
super uid, beginning, end, prev, next, origin
|
||||
if initial_content?
|
||||
@replace initial_content
|
||||
# constructor: (uid, beginning, end, prev, next, origin)->
|
||||
# super uid, beginning, end, prev, next, origin
|
||||
|
||||
type: "ReplaceManager"
|
||||
|
||||
@ -256,24 +254,6 @@ module.exports = (HB)->
|
||||
(new Replaceable content, @, replaceable_uid, o, o.next_cl).execute()
|
||||
undefined
|
||||
|
||||
#
|
||||
# Add change listeners for parent.
|
||||
#
|
||||
setParent: (parent, property_name)->
|
||||
repl_manager = this
|
||||
@on 'insert', (event, op)->
|
||||
if op.next_cl instanceof types.Delimiter
|
||||
repl_manager.parent.callEvent 'change', property_name, op
|
||||
@on 'change', (event, op)->
|
||||
if repl_manager isnt this
|
||||
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.deleteListener 'insert', addPropertyListener
|
||||
repl_manager.parent.callEvent 'addProperty', property_name, op
|
||||
@on 'insert', addPropertyListener
|
||||
super parent
|
||||
|
||||
#
|
||||
# Get the value of this WordType
|
||||
# @return {String}
|
||||
@ -304,7 +284,6 @@ module.exports = (HB)->
|
||||
|
||||
parser["ReplaceManager"] = (json)->
|
||||
{
|
||||
'content' : content
|
||||
'uid' : uid
|
||||
'prev': prev
|
||||
'next': next
|
||||
@ -312,7 +291,7 @@ module.exports = (HB)->
|
||||
'beginning' : beginning
|
||||
'end' : end
|
||||
} = json
|
||||
new ReplaceManager content, uid, beginning, end, prev, next, origin
|
||||
new ReplaceManager uid, beginning, end, prev, next, origin
|
||||
|
||||
|
||||
#
|
||||
@ -342,16 +321,10 @@ module.exports = (HB)->
|
||||
val: ()->
|
||||
@content
|
||||
|
||||
#
|
||||
# Replace the content of this replaceable with new content.
|
||||
#
|
||||
replace: (content)->
|
||||
@parent.replace content
|
||||
|
||||
applyDelete: ()->
|
||||
if @content?
|
||||
if @next_cl.type isnt "Delimiter"
|
||||
@content.deleteAllListeners()
|
||||
@content.deleteAllObservers()
|
||||
@content.applyDelete()
|
||||
@content.dontSync()
|
||||
@content = null
|
||||
@ -361,16 +334,14 @@ module.exports = (HB)->
|
||||
super
|
||||
|
||||
#
|
||||
# If possible set the replace manager in the content.
|
||||
# @see WordType.setReplaceManager
|
||||
#
|
||||
execute: ()->
|
||||
if not @validateSavedOperations()
|
||||
return false
|
||||
else
|
||||
@content?.setReplaceManager?(@parent)
|
||||
# only fire 'insert-event' (which will result in addProperty and change events),
|
||||
# when content is added. In case of Json, empty content means that this is not the last update,
|
||||
# when content is added.
|
||||
# In case of Json, empty content means that this is not the last update,
|
||||
# since content is deleted when 'applyDelete' was exectuted.
|
||||
ins_result = super(@content?) # @content? whether to fire or not
|
||||
if ins_result
|
||||
|
@ -176,23 +176,6 @@ module.exports = (HB)->
|
||||
delete_ops.push d._encode()
|
||||
@
|
||||
|
||||
#
|
||||
# Replace the content of this word with another one. Concurrent replacements are not merged!
|
||||
# Only one of the replacements will be used.
|
||||
#
|
||||
# @return {WordType} Returns the new WordType object.
|
||||
#
|
||||
replaceText: (text)->
|
||||
# Can only be used if the ReplaceManager was set!
|
||||
# @see WordType.setReplaceManager
|
||||
if @replace_manager?
|
||||
word = (new WordType undefined).execute()
|
||||
word.insertText 0, text
|
||||
@replace_manager.replace(word)
|
||||
word
|
||||
else
|
||||
throw new Error "This type is currently not maintained by a ReplaceManager!"
|
||||
|
||||
#
|
||||
# Get the String-representation of this word.
|
||||
# @return {String} The String-representation of this object.
|
||||
@ -213,18 +196,6 @@ module.exports = (HB)->
|
||||
@val()
|
||||
|
||||
#
|
||||
# @private
|
||||
# In most cases you would embed a WordType in a Replaceable, wich is handled by the ReplaceManager in order
|
||||
# to provide replace functionality.
|
||||
#
|
||||
setReplaceManager: (op)->
|
||||
@saveOperation 'replace_manager', op
|
||||
@validateSavedOperations()
|
||||
@on 'insert', (event, ins)=>
|
||||
@replace_manager?.forwardEvent @, 'change', ins
|
||||
@on 'delete', (event, ins, del)=>
|
||||
@replace_manager?.forwardEvent @, 'change', del
|
||||
#
|
||||
# Bind this WordType to a textfield or input field.
|
||||
#
|
||||
# @example
|
||||
|
@ -135,7 +135,7 @@ module.exports = (HB)->
|
||||
dont_proxy ()->
|
||||
that.xml.removeChild deleted
|
||||
|
||||
@attributes.on ['addProperty', 'change'], (event, property_name, op)->
|
||||
@attributes.on ['add', 'update'], (event, property_name, op)->
|
||||
if op.creator isnt HB.getUserId() and this is that.attributes
|
||||
dont_proxy ()->
|
||||
newval = op.val().val()
|
||||
|
@ -9,11 +9,11 @@ adaptConnector = require "./ConnectorAdapter"
|
||||
# Known values that are supported:
|
||||
# * String
|
||||
# * Integer
|
||||
# * Array
|
||||
# * Array
|
||||
#
|
||||
class Yatta
|
||||
|
||||
#
|
||||
#
|
||||
# @param {String} user_id Unique id of the peer.
|
||||
# @param {Connector} Connector the connector class.
|
||||
#
|
||||
@ -25,21 +25,23 @@ class Yatta
|
||||
@engine = new Engine @HB, type_manager.parser
|
||||
@HB.engine = @engine # TODO: !! only for debugging
|
||||
adaptConnector @connector, @engine, @HB, type_manager.execution_listener
|
||||
first_word = new @types.JsonType(@HB.getReservedUniqueIdentifier()).execute()
|
||||
|
||||
#first_word =
|
||||
@root_element = new @types.JsonType(@HB.getReservedUniqueIdentifier()).execute()
|
||||
###
|
||||
uid_beg = @HB.getReservedUniqueIdentifier()
|
||||
uid_end = @HB.getReservedUniqueIdentifier()
|
||||
beg = (new @types.Delimiter uid_beg, undefined, uid_end).execute()
|
||||
end = (new @types.Delimiter uid_end, beg, undefined).execute()
|
||||
|
||||
@root_element = (new @types.ReplaceManager undefined, @HB.getReservedUniqueIdentifier(), beg, end).execute()
|
||||
@root_element = (new @types.ReplaceManager @HB.getReservedUniqueIdentifier(), beg, end).execute()
|
||||
@root_element.replace first_word, @HB.getReservedUniqueIdentifier()
|
||||
|
||||
###
|
||||
|
||||
#
|
||||
# @return JsonType
|
||||
#
|
||||
getSharedObject: ()->
|
||||
@root_element.val()
|
||||
@root_element
|
||||
|
||||
#
|
||||
# Get the initialized connector.
|
||||
@ -82,14 +84,14 @@ class Yatta
|
||||
#
|
||||
# @see Operation.on
|
||||
#
|
||||
on: ()->
|
||||
@getSharedObject().on arguments...
|
||||
observe: ()->
|
||||
@getSharedObject().observe arguments...
|
||||
|
||||
#
|
||||
# @see Operation.deleteListener
|
||||
#
|
||||
deleteListener: ()->
|
||||
@getSharedObject().deleteListener arguments...
|
||||
unobserve: ()->
|
||||
@getSharedObject().unobserve arguments...
|
||||
|
||||
#
|
||||
# @see JsonType.value
|
||||
|
@ -73,11 +73,12 @@ describe "JsonFramework", ->
|
||||
console.log "" # TODO
|
||||
@yTest.run()
|
||||
|
||||
it "has a change listener", ()->
|
||||
### TODO
|
||||
it "has a update listener", ()->
|
||||
addName = false
|
||||
change = false
|
||||
change2 = 0
|
||||
@test_user.on 'addProperty', (eventname, property_name)->
|
||||
@test_user.on 'add', (eventname, property_name)->
|
||||
if property_name is 'x'
|
||||
addName = true
|
||||
@test_user.val('x',5)
|
||||
@ -86,7 +87,7 @@ describe "JsonFramework", ->
|
||||
change = true
|
||||
@test_user.val('x', 6)
|
||||
@test_user.val('ins', "text", 'mutable')
|
||||
@test_user.on 'change', (eventname, property_name)->
|
||||
@test_user.on 'update', (eventname, property_name)->
|
||||
if property_name is 'ins'
|
||||
change2++
|
||||
@test_user.val('ins').insertText 4, " yay"
|
||||
@ -94,6 +95,7 @@ describe "JsonFramework", ->
|
||||
expect(addName).to.be.ok
|
||||
expect(change).to.be.ok
|
||||
expect(change2).to.equal 8
|
||||
###
|
||||
|
||||
it "has a JsonTypeWrapper", ->
|
||||
y = this.yTest.getSomeUser().getSharedObject()
|
||||
|
Loading…
x
Reference in New Issue
Block a user