Adding to HB is now handled by Operation.execute. engine changed. Currently fixing errors and working on memory menagement for large HB tables

This commit is contained in:
DadaMonad 2014-12-16 11:21:57 +00:00
parent 7696864841
commit 2cf899418a
64 changed files with 3013 additions and 10106 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
!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

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

1950
build/browser/yatta.js Normal file

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

@ -13,7 +13,7 @@
mocha.ui('bdd'); mocha.ui('bdd');
mocha.reporter('html'); mocha.reporter('html');
</script> </script>
<script src="TextYatta_test.js"></script> <!--script src="TextYatta_test.js"></script-->
<script src="JsonYatta_test.js"></script> <script src="JsonYatta_test.js"></script>
<!--script src="XmlYatta_test_browser.js"></script--> <!--script src="XmlYatta_test_browser.js"></script-->
<script> <script>

@ -35,11 +35,6 @@
<ul> <ul>
<li class='letter'>j</li> <li class='letter'>j</li>
<ul> <ul>
<li>
<a href='class/JsonFramework.html'>
JsonFramework
</a>
</li>
<li> <li>
<a href='class/JsonTypeWrapper.html'> <a href='class/JsonTypeWrapper.html'>
JsonTypeWrapper JsonTypeWrapper
@ -52,16 +47,6 @@
</li> </li>
</ul> </ul>
</ul> </ul>
<ul>
<li class='letter'>t</li>
<ul>
<li>
<a href='class/TextFramework.html'>
TextFramework
</a>
</li>
</ul>
</ul>
<ul> <ul>
<li class='letter'>w</li> <li class='letter'>w</li>
<ul> <ul>
@ -73,11 +58,11 @@
</ul> </ul>
</ul> </ul>
<ul> <ul>
<li class='letter'>x</li> <li class='letter'>y</li>
<ul> <ul>
<li> <li>
<a href='class/XmlFramework.html'> <a href='class/Yatta.html'>
XmlFramework Yatta
</a> </a>
</li> </li>
</ul> </ul>
@ -137,30 +122,9 @@
</li> </li>
</ul> </ul>
</ul> </ul>
<ul>
<li class='letter'>i</li>
<ul>
<li>
<a href='file/lib/index.coffee.html'>
index.coffee
</a>
<small>
(lib)
</small>
</li>
</ul>
</ul>
<ul> <ul>
<li class='letter'>j</li> <li class='letter'>j</li>
<ul> <ul>
<li>
<a href='file/lib/Frameworks/JsonFramework.coffee.html'>
JsonFramework.coffee
</a>
<small>
(lib&#47;Frameworks)
</small>
</li>
<li> <li>
<a href='file/lib/Types/JsonTypes.coffee.html'> <a href='file/lib/Types/JsonTypes.coffee.html'>
JsonTypes.coffee JsonTypes.coffee
@ -187,14 +151,6 @@
<ul> <ul>
<li class='letter'>t</li> <li class='letter'>t</li>
<ul> <ul>
<li>
<a href='file/lib/Frameworks/TextFramework.coffee.html'>
TextFramework.coffee
</a>
<small>
(lib&#47;Frameworks)
</small>
</li>
<li> <li>
<a href='file/lib/Types/TextTypes.coffee.html'> <a href='file/lib/Types/TextTypes.coffee.html'>
TextTypes.coffee TextTypes.coffee
@ -206,14 +162,14 @@
</ul> </ul>
</ul> </ul>
<ul> <ul>
<li class='letter'>x</li> <li class='letter'>y</li>
<ul> <ul>
<li> <li>
<a href='file/lib/Frameworks/XmlFramework.coffee.html'> <a href='file/lib/Yatta.coffee.html'>
XmlFramework.coffee Yatta.coffee
</a> </a>
<small> <small>
(lib&#47;Frameworks) (lib)
</small> </small>
</li> </li>
</ul> </ul>
@ -222,7 +178,7 @@
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -155,7 +155,7 @@ Known values that are supported:</p><ul>
<p class='signature' id='constructor-dynamic'> <p class='signature' id='constructor-dynamic'>
# #
(void) (void)
<b>constructor</b><span>(user_id, connector)</span> <b>constructor</b><span>(connector)</span>
<br> <br>
</p> </p>
<div class='tags'> <div class='tags'>
@ -335,7 +335,7 @@ JsonFramework was initialized (Depending on the HistoryBuffer implementation).</
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:32:37 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -467,7 +467,7 @@ Otherwise you will loose all the sharing-abilities (the new object will be a dee
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -139,7 +139,7 @@ console.log(w.newProperty == &quot;Awesome&quot;) # true!</code></pre>
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -356,7 +356,7 @@ JsonFramework was initialized (Depending on the HistoryBuffer implementation).</
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:32:37 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -455,7 +455,7 @@ yatta.bind(textbox);</code></pre>
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -303,7 +303,7 @@ JsonFramework was initialized (Depending on the HistoryBuffer implementation).</
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:32:37 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

409
doc/class/Yatta.html Normal file

@ -0,0 +1,409 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<title>Yatta! API</title>
<script src='../javascript/application.js'></script>
<script src='../javascript/search.js'></script>
<link rel='stylesheet' href='../stylesheets/application.css' type='text/css'>
</head>
<body>
<div id='base' data-path='../'></div>
<div id='header'>
<div id='menu'>
<a href='../extra/README.md.html' title='Yatta!'>
Yatta!
</a>
&raquo;
<a href='../alphabetical_index.html' title='Index'>
Index
</a>
&raquo;
<span class='title'>Yatta</span>
</div>
</div>
<div id='content'>
<h1>
Class:
Yatta
</h1>
<table class='box'>
<tr>
<td>Defined in:</td>
<td>lib&#47;Yatta.coffee</td>
</tr>
</table>
<h2>Overview</h2>
<div class='docstring'>
<p>Framework for Json data-structures.
Known values that are supported:</p><ul>
<li>String</li>
<li>Integer</li>
<li>Array</li>
</ul>
</div>
<div class='tags'>
</div>
<h2>Instance Method Summary</h2>
<ul class='summary'>
<li>
<span class='signature'>
<a href='#getSharedObject-dynamic'>
#
(?)
<b>getSharedObject</b><span>()</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#getConnector-dynamic'>
#
(void)
<b>getConnector</b><span>()</span>
</a>
</span>
<span class='desc'>
Get the initialized connector.
</span>
</li>
<li>
<span class='signature'>
<a href='#getHistoryBuffer-dynamic'>
#
(void)
<b>getHistoryBuffer</b><span>()</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#setMutableDefault-dynamic'>
#
(void)
<b>setMutableDefault</b><span>(mutable)</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#getUserId-dynamic'>
#
(void)
<b>getUserId</b><span>()</span>
</a>
</span>
<span class='desc'>
Get the UserId from the HistoryBuffer object.
</span>
</li>
<li>
<span class='signature'>
<a href='#toJson-dynamic'>
#
(void)
<b>toJson</b><span>()</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#val-dynamic'>
#
(void)
<b>val</b><span>()</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#on-dynamic'>
#
(void)
<b>on</b><span>()</span>
</a>
</span>
<span class='desc'>
</span>
</li>
<li>
<span class='signature'>
<a href='#deleteListener-dynamic'>
#
(void)
<b>deleteListener</b><span>()</span>
</a>
</span>
<span class='desc'>
</span>
</li>
</ul>
<h2>Constructor Details</h2>
<div class='methods'>
<div class='method_details'>
<p class='signature' id='constructor-dynamic'>
#
(void)
<b>constructor</b><span>(connector)</span>
<br>
</p>
<div class='tags'>
<h3>Parameters:</h3>
<ul class='param'>
<li>
<span class='name'>user_id</span>
<span class='type'>
(
<tt>String</tt>
)
</span>
&mdash;
<span class='desc'>Unique id of the peer. </span>
</li>
<li>
<span class='name'>Connector</span>
<span class='type'>
(
<tt>Connector</tt>
)
</span>
&mdash;
<span class='desc'>the connector class. </span>
</li>
</ul>
</div>
</div>
</div>
<h2>Instance Method Details</h2>
<div class='methods'>
<div class='method_details'>
<p class='signature' id='getSharedObject-dynamic'>
#
(?)
<b>getSharedObject</b><span>()</span>
<br>
</p>
<div class='tags'>
<h3>Returns:</h3>
<ul class='return'>
<li>
<span class='type'></span>
(
<tt>?</tt>
)
&mdash;
<span class='desc'>JsonType </span>
</li>
</ul>
</div>
</div>
<div class='method_details'>
<p class='signature' id='getConnector-dynamic'>
#
(void)
<b>getConnector</b><span>()</span>
<br>
</p>
<div class='docstring'>
<p>Get the initialized connector.</p>
</div>
<div class='tags'>
</div>
</div>
<div class='method_details'>
<p class='signature' id='getHistoryBuffer-dynamic'>
#
(void)
<b>getHistoryBuffer</b><span>()</span>
<br>
</p>
<div class='tags'>
<h3>See also:</h3>
<ul class='see'>
<li>
<a href='HistoryBuffer'>HistoryBuffer</a>
</li>
</ul>
</div>
</div>
<div class='method_details'>
<p class='signature' id='setMutableDefault-dynamic'>
#
(void)
<b>setMutableDefault</b><span>(mutable)</span>
<br>
</p>
<div class='tags'>
<h3>See also:</h3>
<ul class='see'>
<li>
<a href='JsonType.setMutableDefault'>JsonType.setMutableDefault</a>
</li>
</ul>
</div>
</div>
<div class='method_details'>
<p class='signature' id='getUserId-dynamic'>
#
(void)
<b>getUserId</b><span>()</span>
<br>
</p>
<div class='docstring'>
<p>Get the UserId from the HistoryBuffer object.
In most cases this will be the same as the user_id value with which
Yatta was initialized (Depending on the HistoryBuffer implementation).</p>
</div>
<div class='tags'>
</div>
</div>
<div class='method_details'>
<p class='signature' id='toJson-dynamic'>
#
(void)
<b>toJson</b><span>()</span>
<br>
</p>
<div class='tags'>
<h3>See also:</h3>
<ul class='see'>
<li>
<a href='JsonType.toJson'>JsonType.toJson</a>
</li>
</ul>
</div>
</div>
<div class='method_details'>
<p class='signature' id='val-dynamic'>
#
(void)
<b>val</b><span>()</span>
<br>
</p>
<div class='tags'>
<h3>See also:</h3>
<ul class='see'>
<li>
<a href='JsonType.val'>JsonType.val</a>
</li>
</ul>
</div>
</div>
<div class='method_details'>
<p class='signature' id='on-dynamic'>
#
(void)
<b>on</b><span>()</span>
<br>
</p>
<div class='tags'>
<h3>See also:</h3>
<ul class='see'>
<li>
<a href='Operation.on'>Operation.on</a>
</li>
</ul>
</div>
</div>
<div class='method_details'>
<p class='signature' id='deleteListener-dynamic'>
#
(void)
<b>deleteListener</b><span>()</span>
<br>
</p>
<div class='tags'>
<h3>See also:</h3>
<ul class='see'>
<li>
<a href='Operation.deleteListener'>Operation.deleteListener</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div id='footer'>
December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>
2.0.9
&#10034;
Press H to see the keyboard shortcuts
&#10034;
<a href='http://twitter.com/netzpirat' target='_parent'>@netzpirat</a>
&#10034;
<a href='http://twitter.com/_inossidabile' target='_parent'>@_inossidabile</a>
</div>
<iframe id='search_frame'></iframe>
<div id='fuzzySearch'>
<input type='text'>
<ol></ol>
</div>
<div id='help'>
<p>
Quickly fuzzy find classes, mixins, methods, file:
</p>
<ul>
<li>
<span>T</span>
Open fuzzy finder dialog
</li>
</ul>
<p>
Control the navigation frame:
</p>
<ul>
<li>
<span>L</span>
Toggle list view
</li>
<li>
<span>C</span>
Show class list
</li>
<li>
<span>I</span>
Show mixin list
</li>
<li>
<span>F</span>
Show file list
</li>
<li>
<span>M</span>
Show method list
</li>
<li>
<span>E</span>
Show extras list
</li>
</ul>
<p>
You can focus and blur the search input:
</p>
<ul>
<li>
<span>S</span>
Focus search input
</li>
<li>
<span>Esc</span>
Blur search input
</li>
</ul>
</div>
</body>
</html>

@ -29,30 +29,6 @@
<input type='text'> <input type='text'>
</div> </div>
<ul> <ul>
<li>
<a href='class/JsonFramework.html' target='main'>
JsonFramework
</a>
<small class='namespace'>
</small>
</li>
<li>
<a href='class/TextFramework.html' target='main'>
TextFramework
</a>
<small class='namespace'>
</small>
</li>
<li>
<a href='class/XmlFramework.html' target='main'>
XmlFramework
</a>
<small class='namespace'>
</small>
</li>
<li> <li>
<a href='class/JsonTypeWrapper.html' target='main'> <a href='class/JsonTypeWrapper.html' target='main'>
JsonTypeWrapper JsonTypeWrapper
@ -83,6 +59,14 @@
</small> </small>
<small class='namespace'> <small class='namespace'>
</small>
</li>
<li>
<a href='class/Yatta.html' target='main'>
Yatta
</a>
<small class='namespace'>
</small> </small>
</li> </li>
</ul> </ul>

@ -38,7 +38,7 @@
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -34,7 +34,7 @@
</p> </p>
</nav> </nav>
<div id='filecontents'> <div id='filecontents'>
<h1 id="-yatta-extras-imgs-yatta_logo-png-raw-true-"><img src="./extras/imgs/Yatta_logo.png?raw=true" alt="Yatta!"></h1><p>A Real-Time web framework that manages concurrency control for arbitrary data structures. <h1 id="-yatta-https-dadamonad-github-io-files-layout-yatta_logo-png-"><img src="https://dadamonad.github.io/files/layout/Yatta_logo.png" alt="Yatta!"></h1><p>A Real-Time web framework that manages concurrency control for arbitrary data structures.
Yatta! provides similar functionality as <a href="https://github.com/share/ShareJS">ShareJs</a> and <a href="https://github.com/opencoweb/coweb">OpenCoweb</a>, Yatta! provides similar functionality as <a href="https://github.com/share/ShareJS">ShareJs</a> and <a href="https://github.com/opencoweb/coweb">OpenCoweb</a>,
but does not require you to understand how the internals work. The predefined data structures provide a simple API to access your shared data structures.</p><p>Predefined data structures:</p><ul> but does not require you to understand how the internals work. The predefined data structures provide a simple API to access your shared data structures.</p><p>Predefined data structures:</p><ul>
<li>Text - <a href="http://dadamonad.github.io/Yatta/examples/TextEditing/">Collaborative Text Editing Example</a></li> <li>Text - <a href="http://dadamonad.github.io/Yatta/examples/TextEditing/">Collaborative Text Editing Example</a></li>
@ -76,7 +76,7 @@ But I would become really motivated if you gave me some feedback :) (<a href="ht
</ul> </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>! <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, 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&#39;t support.</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;&#x6c;&#x74;&#x6f;&#58;&#x6b;&#x65;&#118;&#105;&#x6e;&#x2e;&#106;&#97;&#104;&#110;&#x73;&#x40;&#114;&#x77;&#116;&#x68;&#45;&#x61;&#97;&#x63;&#104;&#x65;&#110;&#46;&#100;&#x65;">&#x6b;&#x65;&#118;&#105;&#x6e;&#x2e;&#106;&#97;&#104;&#110;&#x73;&#x40;&#114;&#x77;&#116;&#x68;&#45;&#x61;&#97;&#x63;&#104;&#x65;&#110;&#46;&#100;&#x65;</a> please state function name, and sample parameters. However, there are browser-specific features, that Yatta won&#39;t support.</p><h2 id="license">License</h2><p>Yatta! is licensed under the <a href="./LICENSE.txt">MIT License</a>.</p><a href="&#109;&#x61;&#x69;&#108;&#x74;&#111;&#x3a;&#x6b;&#x65;&#118;&#x69;&#x6e;&#46;&#106;&#x61;&#104;&#x6e;&#x73;&#64;&#114;&#119;&#116;&#x68;&#x2d;&#x61;&#x61;&#99;&#x68;&#x65;&#110;&#x2e;&#100;&#101;">&#x6b;&#x65;&#118;&#x69;&#x6e;&#46;&#106;&#x61;&#104;&#x6e;&#x73;&#64;&#114;&#119;&#116;&#x68;&#x2d;&#x61;&#x61;&#99;&#x68;&#x65;&#110;&#x2e;&#100;&#101;</a>
@ -85,7 +85,7 @@ please state function name, and sample parameters. However, there are browser-sp
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -106,7 +106,7 @@
</div> </div>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -48,7 +48,7 @@
</dl> </dl>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -60,7 +60,7 @@
</dl> </dl>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:32:37 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -60,7 +60,7 @@
</dl> </dl>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:32:37 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -60,7 +60,7 @@
</dl> </dl>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:32:37 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -48,7 +48,7 @@
</dl> </dl>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -39,7 +39,7 @@
</table> </table>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -39,7 +39,7 @@
</table> </table>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -39,7 +39,7 @@
</table> </table>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -39,7 +39,7 @@
</table> </table>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<title>Yatta! API</title>
<script src='../../javascript/application.js'></script>
<script src='../../javascript/search.js'></script>
<link rel='stylesheet' href='../../stylesheets/application.css' type='text/css'>
</head>
<body>
<div id='base' data-path='../../'></div>
<div id='header'>
<div id='menu'>
<a href='../../extra/README.md.html' title='Yatta!'>
Yatta!
</a>
&raquo;
<a href='../../alphabetical_index.html' title='Index'>
Index
</a>
&raquo;
<span class='title'>lib</span>
&raquo;
<span class='title'>Yatta.coffee</span>
</div>
</div>
<div id='content'>
<h1>
File:
Yatta.coffee
</h1>
<table class='box'>
<tr>
<td>Defined in:</td>
<td>lib</td>
</tr>
<tr>
<td>
Classes:
</td>
<td>
<a href='../../class/Yatta.html'>
Yatta
</a>
</td>
</tr>
</table>
<h2>Variables Summary</h2>
<dl class='constants'>
<dt id='module.exports-variable'>
module.exports
=
</dt>
<dd>
<pre><code class='coffeescript'>Yatta</code></pre>
</dd>
</dl>
</div>
<div id='footer'>
December 16, 14 09:44:06 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo
</a>
2.0.9
&#10034;
Press H to see the keyboard shortcuts
&#10034;
<a href='http://twitter.com/netzpirat' target='_parent'>@netzpirat</a>
&#10034;
<a href='http://twitter.com/_inossidabile' target='_parent'>@_inossidabile</a>
</div>
<iframe id='search_frame'></iframe>
<div id='fuzzySearch'>
<input type='text'>
<ol></ol>
</div>
<div id='help'>
<p>
Quickly fuzzy find classes, mixins, methods, file:
</p>
<ul>
<li>
<span>T</span>
Open fuzzy finder dialog
</li>
</ul>
<p>
Control the navigation frame:
</p>
<ul>
<li>
<span>L</span>
Toggle list view
</li>
<li>
<span>C</span>
Show class list
</li>
<li>
<span>I</span>
Show mixin list
</li>
<li>
<span>F</span>
Show file list
</li>
<li>
<span>M</span>
Show method list
</li>
<li>
<span>E</span>
Show extras list
</li>
</ul>
<p>
You can focus and blur the search input:
</p>
<ul>
<li>
<span>S</span>
Focus search input
</li>
<li>
<span>Esc</span>
Blur search input
</li>
</ul>
</div>
</body>
</html>

@ -37,7 +37,7 @@
</table> </table>
</div> </div>
<div id='footer'> <div id='footer'>
December 02, 14 09:37:37 by December 16, 14 09:32:37 by
<a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'> <a href='https://github.com/coffeedoc/codo' title='CoffeeScript API documentation generator'>
Codo Codo
</a> </a>

@ -51,38 +51,6 @@
lib lib
</small> </small>
</li> </li>
<li>
<span>
Frameworks
</span>
</li>
<ul>
<li>
<a href='file/lib/Frameworks/JsonFramework.coffee.html' target='main'>
JsonFramework.coffee
</a>
<small class='namespace'>
lib&#47;Frameworks
</small>
</li>
<li>
<a href='file/lib/Frameworks/TextFramework.coffee.html' target='main'>
TextFramework.coffee
</a>
<small class='namespace'>
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> <li>
<a href='file/lib/HistoryBuffer.coffee.html' target='main'> <a href='file/lib/HistoryBuffer.coffee.html' target='main'>
HistoryBuffer.coffee HistoryBuffer.coffee
@ -132,8 +100,8 @@
</ul> </ul>
<li> <li>
<a href='file/lib/index.coffee.html' target='main'> <a href='file/lib/Yatta.coffee.html' target='main'>
index.coffee Yatta.coffee
</a> </a>
<small class='namespace'> <small class='namespace'>
lib lib

File diff suppressed because one or more lines are too long

@ -29,14 +29,6 @@
<input type='text'> <input type='text'>
</div> </div>
<ul> <ul>
<li>
<a href='class/WordType.html#_encode-dynamic' target='main' title='_encode'>
#_encode
</a>
<small>
(WordType)
</small>
</li>
<li> <li>
<a href='class/JsonType.html#_encode-dynamic' target='main' title='_encode'> <a href='class/JsonType.html#_encode-dynamic' target='main' title='_encode'>
#_encode #_encode
@ -45,6 +37,14 @@
(JsonType) (JsonType)
</small> </small>
</li> </li>
<li>
<a href='class/WordType.html#_encode-dynamic' target='main' title='_encode'>
#_encode
</a>
<small>
(WordType)
</small>
</li>
<li> <li>
<a href='file/lib/ConnectorAdapter.coffee.html#adaptConnector-' target='main' title='adaptConnector'> <a href='file/lib/ConnectorAdapter.coffee.html#adaptConnector-' target='main' title='adaptConnector'>
~adaptConnector ~adaptConnector
@ -70,16 +70,16 @@
</small> </small>
</li> </li>
<li> <li>
<a href='class/TextFramework.html#bind-dynamic' target='main' title='bind'> <a href='class/WordType.html#bind-dynamic' target='main' title='bind'>
#bind #bind
</a> </a>
<small> <small>
(TextFramework) (WordType)
</small> </small>
</li> </li>
<li> <li>
<a href='class/WordType.html#bind-dynamic' target='main' title='bind'> <a href='class/WordType.html#cleanup-dynamic' target='main' title='cleanup'>
#bind #cleanup
</a> </a>
<small> <small>
(WordType) (WordType)
@ -94,43 +94,11 @@
</small> </small>
</li> </li>
<li> <li>
<a href='class/WordType.html#cleanup-dynamic' target='main' title='cleanup'> <a href='class/Yatta.html#constructor-dynamic' target='main' title='constructor'>
#cleanup
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/JsonTypeWrapper.html#constructor-dynamic' target='main' title='constructor'>
#constructor #constructor
</a> </a>
<small> <small>
(JsonTypeWrapper) (Yatta)
</small>
</li>
<li>
<a href='class/TextFramework.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/WordType.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/XmlFramework.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(XmlFramework)
</small> </small>
</li> </li>
<li> <li>
@ -142,27 +110,27 @@
</small> </small>
</li> </li>
<li> <li>
<a href='class/JsonFramework.html#constructor-dynamic' target='main' title='constructor'> <a href='class/JsonTypeWrapper.html#constructor-dynamic' target='main' title='constructor'>
#constructor #constructor
</a> </a>
<small> <small>
(JsonFramework) (JsonTypeWrapper)
</small> </small>
</li> </li>
<li> <li>
<a href='class/JsonFramework.html#deleteListener-dynamic' target='main' title='deleteListener'> <a href='class/WordType.html#constructor-dynamic' target='main' title='constructor'>
#constructor
</a>
<small>
(WordType)
</small>
</li>
<li>
<a href='class/Yatta.html#deleteListener-dynamic' target='main' title='deleteListener'>
#deleteListener #deleteListener
</a> </a>
<small> <small>
(JsonFramework) (Yatta)
</small>
</li>
<li>
<a href='class/TextFramework.html#deleteText-dynamic' target='main' title='deleteText'>
#deleteText
</a>
<small>
(TextFramework)
</small> </small>
</li> </li>
<li> <li>
@ -174,51 +142,19 @@
</small> </small>
</li> </li>
<li> <li>
<a href='class/XmlFramework.html#getConnector-dynamic' target='main' title='getConnector'> <a href='class/Yatta.html#getConnector-dynamic' target='main' title='getConnector'>
#getConnector #getConnector
</a> </a>
<small> <small>
(XmlFramework) (Yatta)
</small> </small>
</li> </li>
<li> <li>
<a href='class/TextFramework.html#getConnector-dynamic' target='main' title='getConnector'> <a href='class/Yatta.html#getHistoryBuffer-dynamic' target='main' title='getHistoryBuffer'>
#getConnector
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#getConnector-dynamic' target='main' title='getConnector'>
#getConnector
</a>
<small>
(JsonFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#getHistoryBuffer-dynamic' target='main' title='getHistoryBuffer'>
#getHistoryBuffer #getHistoryBuffer
</a> </a>
<small> <small>
(XmlFramework) (Yatta)
</small>
</li>
<li>
<a href='class/TextFramework.html#getHistoryBuffer-dynamic' target='main' title='getHistoryBuffer'>
#getHistoryBuffer
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#getHistoryBuffer-dynamic' target='main' title='getHistoryBuffer'>
#getHistoryBuffer
</a>
<small>
(JsonFramework)
</small> </small>
</li> </li>
<li> <li>
@ -230,51 +166,19 @@
</small> </small>
</li> </li>
<li> <li>
<a href='class/JsonFramework.html#getSharedObject-dynamic' target='main' title='getSharedObject'> <a href='class/Yatta.html#getSharedObject-dynamic' target='main' title='getSharedObject'>
#getSharedObject #getSharedObject
</a> </a>
<small> <small>
(JsonFramework) (Yatta)
</small> </small>
</li> </li>
<li> <li>
<a href='class/XmlFramework.html#getSharedObject-dynamic' target='main' title='getSharedObject'> <a href='class/Yatta.html#getUserId-dynamic' target='main' title='getUserId'>
#getSharedObject
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#getSharedObject-dynamic' target='main' title='getSharedObject'>
#getSharedObject
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId #getUserId
</a> </a>
<small> <small>
(XmlFramework) (Yatta)
</small>
</li>
<li>
<a href='class/JsonFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId
</a>
<small>
(JsonFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#getUserId-dynamic' target='main' title='getUserId'>
#getUserId
</a>
<small>
(TextFramework)
</small> </small>
</li> </li>
<li> <li>
@ -294,35 +198,11 @@
</small> </small>
</li> </li>
<li> <li>
<a href='class/TextFramework.html#insertText-dynamic' target='main' title='insertText'> <a href='class/Yatta.html#on-dynamic' target='main' title='on'>
#insertText
</a>
<small>
(TextFramework)
</small>
</li>
<li>
<a href='class/JsonFramework.html#on-dynamic' target='main' title='on'>
#on #on
</a> </a>
<small> <small>
(JsonFramework) (Yatta)
</small>
</li>
<li>
<a href='class/XmlFramework.html#on-dynamic' target='main' title='on'>
#on
</a>
<small>
(XmlFramework)
</small>
</li>
<li>
<a href='class/TextFramework.html#on-dynamic' target='main' title='on'>
#on
</a>
<small>
(TextFramework)
</small> </small>
</li> </li>
<li> <li>
@ -333,14 +213,6 @@
(WordType) (WordType)
</small> </small>
</li> </li>
<li>
<a href='class/TextFramework.html#replaceText-dynamic' target='main' title='replaceText'>
#replaceText
</a>
<small>
(TextFramework)
</small>
</li>
<li> <li>
<a href='class/WordType.html#replaceText-dynamic' target='main' title='replaceText'> <a href='class/WordType.html#replaceText-dynamic' target='main' title='replaceText'>
#replaceText #replaceText
@ -349,14 +221,6 @@
(WordType) (WordType)
</small> </small>
</li> </li>
<li>
<a href='class/JsonFramework.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
#setMutableDefault
</a>
<small>
(JsonFramework)
</small>
</li>
<li> <li>
<a href='class/JsonType.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'> <a href='class/JsonType.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
#setMutableDefault #setMutableDefault
@ -366,11 +230,11 @@
</small> </small>
</li> </li>
<li> <li>
<a href='class/XmlFramework.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'> <a href='class/Yatta.html#setMutableDefault-dynamic' target='main' title='setMutableDefault'>
#setMutableDefault #setMutableDefault
</a> </a>
<small> <small>
(XmlFramework) (Yatta)
</small> </small>
</li> </li>
<li> <li>
@ -389,22 +253,6 @@
(WordType) (WordType)
</small> </small>
</li> </li>
<li>
<a href='class/JsonFramework.html#toJson-dynamic' target='main' title='toJson'>
#toJson
</a>
<small>
(JsonFramework)
</small>
</li>
<li>
<a href='class/XmlFramework.html#toJson-dynamic' target='main' title='toJson'>
#toJson
</a>
<small>
(XmlFramework)
</small>
</li>
<li> <li>
<a href='class/JsonType.html#toJson-dynamic' target='main' title='toJson'> <a href='class/JsonType.html#toJson-dynamic' target='main' title='toJson'>
#toJson #toJson
@ -413,6 +261,14 @@
(JsonType) (JsonType)
</small> </small>
</li> </li>
<li>
<a href='class/Yatta.html#toJson-dynamic' target='main' title='toJson'>
#toJson
</a>
<small>
(Yatta)
</small>
</li>
<li> <li>
<a href='class/WordType.html#toString-dynamic' target='main' title='toString'> <a href='class/WordType.html#toString-dynamic' target='main' title='toString'>
#toString #toString
@ -422,19 +278,11 @@
</small> </small>
</li> </li>
<li> <li>
<a href='class/JsonFramework.html#val-dynamic' target='main' title='val'> <a href='class/Yatta.html#val-dynamic' target='main' title='val'>
#val #val
</a> </a>
<small> <small>
(JsonFramework) (Yatta)
</small>
</li>
<li>
<a href='class/XmlFramework.html#val-dynamic' target='main' title='val'>
#val
</a>
<small>
(XmlFramework)
</small> </small>
</li> </li>
<li> <li>
@ -445,14 +293,6 @@
(WordType) (WordType)
</small> </small>
</li> </li>
<li>
<a href='class/TextFramework.html#val-dynamic' target='main' title='val'>
#val
</a>
<small>
(TextFramework)
</small>
</li>
<li> <li>
<a href='class/JsonType.html#val-dynamic' target='main' title='val'> <a href='class/JsonType.html#val-dynamic' target='main' title='val'>
#val #val

@ -1,333 +0,0 @@
## 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/JsonFramework.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;
```
This will connect to the server owned by the peerjs team.
For now, you can use my API key.
```js
//var options = {key: 'h7nlefbgavh1tt9'};
```
This will connect to one of my peerjs instances.
I can't guaranty that this will be always up. This is why you should use the previous method with the api key,
or set up your own server.
```js
var options = {
host: "terrific-peerjs.herokuapp.com",
port: "", // this works because heroku can forward to the right port.
// debug: true,
};
var user_id = Math.ceil(Math.random()*100);
connector = new PeerJsConnector(user_id,options);
//var connector = new TestConnector(user_id);
```
### Yatta
yatta is the shared json object. If you change something on this object,
it will be instantly shared with all the other collaborators.
```js
yatta = new Y.JsonFramework(user_id, connector);
```
Next, you may want to connect to another peer. Therefore you have to receive his
user_id. If the other peer is connected to other peers, the PeerJsConnector
will automatically connect to them too.
Transmitting the user_id is your job.
See [TextEditing](../../examples/TextEditing/) for a nice example
on how to do that with urls.
```js
console.log("Copy your user-id: " + user_id);
// yatta.connector.connectToPeer(peer_user_id);
```
Add a integer-property like this
```js
yatta.val('x', 7);
```
Get the value of property x like this
```js
console.log(yatta.val('x') === 7); // true
```
A string property can be either mutable or immutable.
```js
yatta.val('mutable_string', "text", "mutable");
yatta.val('immutable_string', "text", "immutable");
console.log(yatta.val('immutable_string') === "text"); // true
yatta.val('mutable_string').insertText(2,"XXX"); // position, string
yatta.val('mutable_string').deleteText(0,1); // position, deletion length
console.log(yatta.val('mutable_string').val() === "eXXXxt"); // true
```
Did you recognize that we use anoter `.val()` for mutable strings?
Thats because `yatta.val('mutable_string')` is of type *WordType*.
Since WordType implements `toString`, you can use it like a string:
```js
console.log("" + yatta.val("mutable_string") === "eXXXxt") // true, concatenating it with a string will implicitly invoke toString()
```
You can omit the mutable - parameter. In that case the default will be used.
Initially the default is 'mutable'. You can set it like this:
```js
yatta.setMutableDefault('mutable');
// or
yatta.setMutableDefault('immutable');
yatta.val('new_string', "string");
console.log(yatta.val('new_string') === "string"); // true
```
Yatta is [chainable](http://schier.co/post/method-chaining-in-javascript):
```js
yatta.val('a', 4).val('b',5);
console.log(yatta.val('a') === 4); // true
console.log(yatta.val('b') === 5); // true
```
You can alse set objects.
```js
yatta.val('object', {a : {b : "b"}, c : { d : 5 }});
console.log(yatta.val('object').val('c').val('d') === 5); // true
```
Lists are always immutable.
```js
yatta.val('list', [0,1,2]);
console.log(yatta.val('list')[2] === 2); // true
```
### Check Types
Certainly you want to check types!
You get the type of an YattaType with the `.type` property.
Here, we create a function that parses a Yatta type to a string.
```js
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;
}
}
```
### Add listeners
Apply a 'addProperty' - listener to a JsonType.
```js
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);
yatta.val('new', {z: 7}); // Property 'new' was created!
```
Apply a 'change' - listener to a JsonType.
```js
function change(event_name, property_name, op){
// Check who made this property change!
if(op.creator == yatta.getUserId()){
console.log("You changed the value of property '" + property_name + "'!");
}else{
console.log("User '"+op.creator+"' changed the value of property '" + property_name + "'!");
}
console.log("New value: " + show(this.val(property_name)) + ""); // 'this' is the object on which the property changed.
};
yatta.on('change', change);
yatta.val('mutable_string', "text", 'mutable'); // You changed the value of property 'mutable_string'!
```
'change' and 'addProperty' do also fire for nested properties.
```js
yatta.val('new').val('z', {'replace' : "x"}); // Property 'z' was replaced or changed!
yatta.val('new').val('z').val('new', {"true": true}); // Property 'z' was replaced or changed! + Property 'new' was created!
```
Delete the listeners
```js
yatta.deleteListener('addProperty', addProperty);
yatta.deleteListener('change', change);
```
Apply 'insert' and 'delete' - listeners to Words.
```js
function insert_delete(event_name, op){
if (event_name === "insert"){
console.log("Inserted '" + op.content + "' at position " + op.getPosition());
} else if (event_name === "delete"){
console.log("Deleted character at position " + op.getPosition());
}
};
yatta.val('mutable_string').on(['insert', 'delete'], insert_delete);
yatta.val('mutable_string').insertText(0, 'a'); // Inserted 'a' at position 0
yatta.val('mutable_string').deleteText(0, 1); // Deleted character at position 0
yatta.val('mutable_string').deleteListener('insert_delete', insert_delete);
```
### Experimental method
Nah.. this is only for the cool kids.
```js
console.log(yatta.value.list[2] === 2) // true
yatta.value.list = [3,4,5]
console.log(yatta.val('list')[2] === 5) // true
yatta.value.object = {c : 4}
console.log(yatta.value.object.c === 4) // true
```
How did I do that? ^^
In Javascript it is possible set setter- and getter- for properties. This is
why this method feels much more natural.
The downside is that you are only allowed to overwrite existing properties.
```js
yatta.value.newProperty = "Awesome"
console.log(yatta.value.newProperty !== "Awesome") // true, yatta.value.newProperty is undefined.
```
So, how do we create new properties?
```js
yatta.value = {newProperty : "Awesome"}
console.log(yatta.value.newProperty === "Awesome") // true, it's awesome ;)
```
This is stupid! I don't want to overwrite all my existing properties!
Very well.. The solution is that we merge yatta.value with the new assignment.
For example: assuming we want to overwrite yatta.value with some object o.
Then these two rules apply:
* The result has all properties of o
* The result has all properties of yatta.value if they don't occur under the same property-name in o
```js
yatta.value = {newProperty : {Awesome : true }}
console.log(yatta.value.list[2] === 5) // true, old value list still exists.
console.log(yatta.value.newProperty.Awesome === true) // true, newProperty is overwritten.
```
Consider this case.
```js
yatta.value = {newProperty : { x : 4} }
console.log(yatta.value.newProperty.Awesome == null) // true, newProperty was replaced, therefore it is now undefined
```
Did you notice that you always set immutable objects if you set properties like this?
Even if the default is 'mutable'. If you want to work with mutable objects you have to work with .val().
One last thing. You are only allowed to set properties like this `yatta.value = o`.
Yatta can't observe if you overwrite object references `yatta = "Awesome"`.
```js
w = yatta.value.newProperty
w = "Awesome"
console.log(yatta.value.newProperty !== "Awesome") // true, still not awesome..
```
Please also read [JsonWrapper](https://rawgit.com/DadaMonad/Yatta/master/doc/class/JsonWrapper.html).
I really want to hear what you think about this method :)

@ -6,7 +6,7 @@
<script src="../../bower_components/peerjs/peer.js"></script> <script src="../../bower_components/peerjs/peer.js"></script>
<script src="../../bower_components/connector/peerjs-connector/peerjs-connector.js"></script> <script src="../../bower_components/connector/peerjs-connector/peerjs-connector.js"></script>
<script src="../../bower_components/connector/test-connector/test-connector.js"></script> <script src="../../bower_components/connector/test-connector/test-connector.js"></script>
<script src="../../build/browser/Frameworks/JsonFramework.js"></script> <script src="../../build/browser/yatta.js"></script>
<script src="./index.js"></script> <script src="./index.js"></script>
</head> </head>
<body> <body>

@ -29,19 +29,20 @@ var yatta, yattaHandler;
This will connect to the server owned by the peerjs team. This will connect to the server owned by the peerjs team.
For now, you can use my API key. For now, you can use my API key.
*/ */
//var options = {key: 'h7nlefbgavh1tt9'}; var options = {key: 'h7nlefbgavh1tt9'};
/** /**
This will connect to one of my peerjs instances. This will connect to one of my peerjs instances.
I can't guaranty that this will be always up. This is why you should use the previous method with the api key, I can't guaranty that this will be always up. This is why you should use the previous method with the api key,
or set up your own server. or set up your own server.
*/ */
/*
var options = { var options = {
host: "terrific-peerjs.herokuapp.com", host: "terrific-peerjs.herokuapp.com",
port: "", // this works because heroku can forward to the right port. port: "", // this works because heroku can forward to the right port.
// debug: true, // debug: true,
}; };
*/
var user_id = Math.ceil(Math.random()*100); var user_id = Math.ceil(Math.random()*100);
connector = new PeerJsConnector(user_id,options); connector = new PeerJsConnector(user_id,options);
@ -52,7 +53,7 @@ connector = new PeerJsConnector(user_id,options);
yatta is the shared json object. If you change something on this object, yatta is the shared json object. If you change something on this object,
it will be instantly shared with all the other collaborators. it will be instantly shared with all the other collaborators.
*/ */
yatta = new Y.JsonFramework(user_id, connector); yatta = new Yatta(connector);
/** /**
Next, you may want to connect to another peer. Therefore you have to receive his Next, you may want to connect to another peer. Therefore you have to receive his

Binary file not shown.

Before

(image error) Size: 868 KiB

Binary file not shown.

Before

(image error) Size: 9.0 KiB

@ -1,357 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="381.09735"
height="187.42168"
id="svg7976"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Yatta_logo.svg">
<defs
id="defs7978">
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend"
style="overflow:visible">
<path
id="path4310"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mend"
style="overflow:visible">
<path
id="path4316"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(-0.6,-0.6)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mstart"
style="overflow:visible">
<path
id="path4313"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6,0.6)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0"
refX="0"
id="Arrow1Send"
style="overflow:visible">
<path
id="path4304"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Sstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Sstart"
style="overflow:visible">
<path
id="path4301"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(0.2,0,0,0.2,1.2,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible">
<path
id="path4292"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible">
<path
id="path4289"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(0.8,0,0,0.8,10,0)"
inkscape:connector-curvature="0" />
</marker>
<inkscape:path-effect
effect="skeletal"
id="path-effect8752"
is_visible="true"
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 z"
copytype="single_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="0"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
fuse_tolerance="0" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="158.87513"
inkscape:cy="178.66098"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-grids="true"
inkscape:window-width="1280"
inkscape:window-height="979"
inkscape:window-x="-4"
inkscape:window-y="-3"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata7981">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-67.225249,-76.895)">
<g
id="g8648"
transform="matrix(3.8957433,0,0,3.8957433,-180.76316,-209.47544)">
<rect
ry="6.0883365"
rx="0"
y="102.509"
x="63.834892"
height="12.488896"
width="9.4584417"
id="rect7986"
style="fill:#ffbd58;fill-opacity:1;stroke:#ffb8bd;stroke-width:0.38039941;stroke-opacity:1" />
<text
sodipodi:linespacing="0%"
id="text7988"
y="113.49197"
x="64.593651"
style="font-size:13px;font-style:normal;font-weight:normal;line-height:0%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="113.49197"
x="64.593651"
id="tspan7990"
sodipodi:role="line">Y</tspan></text>
</g>
<g
id="g8653"
transform="matrix(3.8957433,0,0,3.8957433,-189.0027,-263.0938)">
<rect
ry="6.0883365"
rx="0"
y="116.27232"
x="87.952286"
height="12.488896"
width="9.4584417"
id="rect7986-6"
style="fill:#ffbd58;fill-opacity:1;stroke:#ffb8bd;stroke-width:0.38039941;stroke-opacity:1" />
<text
sodipodi:linespacing="0%"
id="text7988-7"
y="127.25529"
x="88.238144"
style="font-size:13px;font-style:normal;font-weight:normal;line-height:0%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="127.25529"
x="88.238144"
id="tspan7990-9"
sodipodi:role="line">A</tspan></text>
</g>
<g
id="g8658"
transform="matrix(3.8957433,0,0,3.8957433,-183.96057,-337.86438)">
<rect
ry="6.0883365"
rx="0"
y="135.46521"
x="108.6604"
height="12.488896"
width="9.4584417"
id="rect7986-6-7"
style="fill:#ffbd58;fill-opacity:1;stroke:#ffb8bd;stroke-width:0.38039941;stroke-opacity:1" />
<text
sodipodi:linespacing="0%"
id="text7988-7-9"
y="146.44818"
x="109.41916"
style="font-size:13px;font-style:normal;font-weight:normal;line-height:0%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="146.44818"
x="109.41916"
id="tspan7990-9-0"
sodipodi:role="line">T</tspan></text>
</g>
<g
id="g8663"
transform="matrix(3.8957433,0,0,3.8957433,-266.47882,-397.87764)">
<rect
ry="6.0883365"
rx="0"
y="150.87004"
x="151.84442"
height="12.488896"
width="9.4584417"
id="rect7986-6-4"
style="fill:#ffbd58;fill-opacity:1;stroke:#ffb8bd;stroke-width:0.38039941;stroke-opacity:1" />
<text
sodipodi:linespacing="0%"
id="text7988-7-97"
y="161.85301"
x="152.13028"
style="font-size:13px;font-style:normal;font-weight:normal;line-height:0%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="161.85301"
x="152.13028"
id="tspan7990-9-4"
sodipodi:role="line">A</tspan></text>
</g>
<g
id="g8673"
transform="matrix(3.8957433,0,0,3.8957433,-624.46772,-357.54085)">
<rect
ry="6.0883365"
rx="0"
y="140.51598"
x="265.73914"
height="12.488896"
width="9.4584417"
id="rect7986-6-5"
style="fill:#ffbd58;fill-opacity:1;stroke:#ffb8bd;stroke-width:0.38039941;stroke-opacity:1" />
<text
sodipodi:linespacing="0%"
id="text7988-7-7"
y="151.49895"
x="267.86264"
style="font-size:13px;font-style:normal;font-weight:normal;line-height:0%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="151.49895"
x="267.86264"
id="tspan7990-9-5"
sodipodi:role="line">!</tspan></text>
</g>
<g
id="g8668"
transform="matrix(3.8957433,0,0,3.8957433,-712.02806,-577.9551)">
<rect
ry="6.0883365"
rx="0"
y="168.29517"
x="255.13252"
height="12.488896"
width="9.4584417"
id="rect7986-6-8"
style="fill:#ffbd58;fill-opacity:1;stroke:#ffb8bd;stroke-width:0.38039941;stroke-opacity:1" />
<text
sodipodi:linespacing="0%"
id="text7988-7-3"
y="179.27814"
x="255.89128"
style="font-size:13px;font-style:normal;font-weight:normal;line-height:0%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="179.27814"
x="255.89128"
id="tspan7990-9-00"
sodipodi:role="line">T</tspan></text>
</g>
<path
style="fill:none;stroke:#69ff00;stroke-width:1.94787169;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:none"
d="m 96.675142,237.77416 c 16.915998,34.61882 42.117198,33.88572 61.980908,-0.98383"
id="path8783"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#69ff00;stroke-width:1.94787169;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:none"
d="m 185.71118,237.28685 c 16.91602,34.61881 42.11721,33.88572 61.98091,-0.98384"
id="path8783-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#69ff00;stroke-width:1.94787169;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:none"
d="m 356.89652,237.28685 c 16.916,34.61881 42.11719,33.88572 61.98093,-0.98384"
id="path8783-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:2.33744597;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:2.0999999;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
d="m 299.79777,126.3332 -1.43872,66.18503"
id="path10517"
inkscape:connector-type="polyline"
inkscape:connector-curvature="0"
inkscape:connection-start="#g8668"
inkscape:connection-start-point="d4"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ff4f00;stroke-width:1.55829763;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 258.02225,189.56679 c -6.2228,-60.38318 2.94629,-87.18398 25.5794,-84.60886"
id="path11677"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ff4f00;stroke-width:1.55829763;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 345.28073,188.99654 c 6.2228,-60.38318 -2.94631,-87.18397 -25.57942,-84.60884"
id="path11677-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

Before

(image error) Size: 13 KiB

@ -24,10 +24,9 @@ gulp.task 'build', ['lint', 'browser']
files = files =
lib : ['./lib/**/*.coffee'] lib : ['./lib/**/*.coffee']
build : ['./build/**'] build : ['./build/**']
browser : ['./lib/{Connectors,Frameworks}/**/*'] browser : './lib/Yatta.coffee'
test : ['./test/**/*_test.coffee'] #test : ['./test/**/*_test.coffee']
#test : ['./test/TextYatta_test.coffee'] test : ['./test/JsonYatta_test.coffee']
browser_test : ['./test/**/*_test_browser.coffee']
gulp : ['./gulpfile.coffee'] gulp : ['./gulpfile.coffee']
examples : ['./examples/**/*.js'] examples : ['./examples/**/*.js']
@ -51,16 +50,13 @@ gulp.task 'browser', ->
extensions: ['.coffee'] extensions: ['.coffee']
debug : true debug : true
.pipe rename .pipe rename
basename: "yatta"
extname: ".js" extname: ".js"
.pipe gulp.dest './build/browser' .pipe gulp.dest './build/browser/'
.pipe uglify() .pipe uglify()
.pipe rename .pipe gulp.dest '.'
extname: ".js"
basename: "index"
.pipe gulp.dest './'
.pipe gulpif '!**/', git.add({args : "-A"})
gulp.src (files.test.concat files.browser_test), {read: false} gulp.src files.test, {read: false}
.pipe browserify .pipe browserify
transform: ['coffeeify'] transform: ['coffeeify']
extensions: ['.coffee'] extensions: ['.coffee']

@ -22,6 +22,7 @@ class Engine
else else
throw new Error "You forgot to specify a parser for type #{json.type}. The message is #{JSON.stringify json}." 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(). # 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! # @note You must not use this method when you already have ops in your HB!
@ -30,8 +31,6 @@ class Engine
ops = [] ops = []
for o in ops_json for o in ops_json
ops.push @parseOperation o ops.push @parseOperation o
for o in ops
@HB.addOperation o
for o in ops for o in ops
if not o.execute() if not o.execute()
@unprocessed_ops.push o @unprocessed_ops.push o
@ -64,8 +63,6 @@ class Engine
if @HB.getOperation(o)? if @HB.getOperation(o)?
else if not o.execute() else if not o.execute()
@unprocessed_ops.push o @unprocessed_ops.push o
else
@HB.addOperation o
@tryUnprocessed() @tryUnprocessed()
# #

@ -1,107 +0,0 @@
text_types_uninitialized = require "../Types/TextTypes"
HistoryBuffer = require "../HistoryBuffer"
Engine = require "../Engine"
adaptConnector = require "../ConnectorAdapter"
#
# Framework for Text Datastructures.
#
class TextFramework
#
# @param {String} user_id Uniqe user id that defines this peer.
# @param {Connector} Connector The connector defines how you connect to the other peers.
#
constructor: (user_id, @connector)->
@HB = new HistoryBuffer user_id
text_types = text_types_uninitialized @HB
@types = text_types.types
@engine = new Engine @HB, text_types.parser
adaptConnector @connector, @engine, @HB, text_types.execution_listener
beginning = @HB.addOperation new @types.Delimiter {creator: '_', op_number: '_beginning'} , undefined, undefined
end = @HB.addOperation new @types.Delimiter {creator: '_', op_number: '_end'} , beginning, undefined
beginning.next_cl = end
beginning.execute()
end.execute()
first_word = new @types.WordType {creator: '_', op_number: '_'}, beginning, end
@HB.addOperation(first_word).execute()
uid_r = { creator: '_', op_number: "RM" }
uid_beg = { creator: '_', op_number: "_RM_beginning" }
uid_end = { creator: '_', op_number: "_RM_end" }
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 = @HB.addOperation(new @types.ReplaceManager undefined, uid_r, beg, end).execute()
@root_element.replace first_word, { creator: '_', op_number: 'Replaceable'}
#
# @return WordType
#
getSharedObject: ()->
@root_element.val()
#
# Get the initialized connector.
#
getConnector: ()->
@connector
#
# @see HistoryBuffer
#
getHistoryBuffer: ()->
@HB
#
# 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.val
#
val: ()->
@getSharedObject().val()
#
# @see WordType.insertText
#
insertText: (pos, content)->
@getSharedObject().insertText pos, content
#
# @see WordType.deleteText
#
deleteText: (pos, length)->
@getSharedObject().deleteText pos, length
#
# @see WordType.bind
#
bind: (textarea)->
@getSharedObject().bind textarea
#
# @see WordType.replaceText
#
replaceText: (text)->
@getSharedObject().replaceText text
#
# @see Operation.on
#
on: ()->
@root_element.on arguments...
module.exports = TextFramework
if window?
if not window.Y?
window.Y = {}
window.Y.TextFramework = TextFramework

@ -1,101 +0,0 @@
json_types_uninitialized = require "../Types/XmlTypes"
HistoryBuffer = require "../HistoryBuffer"
Engine = require "../Engine"
adaptConnector = require "../ConnectorAdapter"
#
# 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
adaptConnector @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

@ -26,7 +26,7 @@ class HistoryBuffer
emptyGarbage: ()=> emptyGarbage: ()=>
for o in @garbage for o in @garbage
#if @getOperationCounter(o.creator) > o.op_number #if @getOperationCounter(o.uid.creator) > o.uid.op_number
o.cleanup?() o.cleanup?()
@garbage = @trash @garbage = @trash
@ -104,13 +104,13 @@ class HistoryBuffer
if o.next_cl? # applies for all ops but the most right delimiter! if o.next_cl? # applies for all ops but the most right delimiter!
# search for the next _known_ operation. (When state_vector is {} then this is the Delimiter) # search for the next _known_ operation. (When state_vector is {} then this is the Delimiter)
o_next = o.next_cl o_next = o.next_cl
while o_next.next_cl? and unknown(o_next.creator, o_next.op_number) while o_next.next_cl? and unknown(o_next.uid.creator, o_next.uid.op_number)
o_next = o_next.next_cl o_next = o_next.next_cl
o_json.next = o_next.getUid() o_json.next = o_next.getUid()
else if o.prev_cl? # most right delimiter only! else if o.prev_cl? # most right delimiter only!
# same as the above with prev. # same as the above with prev.
o_prev = o.prev_cl o_prev = o.prev_cl
while o_prev.prev_cl? and unknown(o_prev.creator, o_prev.op_number) while o_prev.prev_cl? and unknown(o_prev.uid.creator, o_prev.uid.op_number)
o_prev = o_prev.prev_cl o_prev = o_prev.prev_cl
o_json.prev = o_prev.getUid() o_json.prev = o_prev.getUid()
json.push o_json json.push o_json
@ -130,6 +130,7 @@ class HistoryBuffer
uid = uid =
'creator' : user_id 'creator' : user_id
'op_number' : @operation_counter[user_id] 'op_number' : @operation_counter[user_id]
'doSync' : true
@operation_counter[user_id]++ @operation_counter[user_id]++
uid uid
@ -147,35 +148,35 @@ class HistoryBuffer
# other operations (it wont executed) # other operations (it wont executed)
# #
addOperation: (o)-> addOperation: (o)->
if not @buffer[o.creator]? if not @buffer[o.uid.creator]?
@buffer[o.creator] = {} @buffer[o.uid.creator] = {}
if @buffer[o.creator][o.op_number]? if @buffer[o.uid.creator][o.uid.op_number]?
throw new Error "You must not overwrite operations!" throw new Error "You must not overwrite operations!"
@buffer[o.creator][o.op_number] = o @buffer[o.uid.creator][o.uid.op_number] = o
@number_of_operations_added_to_HB ?= 0 # TODO: Debug, remove this @number_of_operations_added_to_HB ?= 0 # TODO: Debug, remove this
@number_of_operations_added_to_HB++ @number_of_operations_added_to_HB++
o o
removeOperation: (o)-> removeOperation: (o)->
delete @buffer[o.creator]?[o.op_number] delete @buffer[o.uid.creator]?[o.uid.op_number]
# #
# Increment the operation_counter that defines the current state of the Engine. # Increment the operation_counter that defines the current state of the Engine.
# #
addToCounter: (o)-> addToCounter: (o)->
if not @operation_counter[o.creator]? if not @operation_counter[o.uid.creator]?
@operation_counter[o.creator] = 0 @operation_counter[o.uid.creator] = 0
if typeof o.op_number is 'number' and o.creator isnt @getUserId() if typeof o.uid.op_number is 'number' and o.uid.creator isnt @getUserId()
# TODO: fix this issue better. # TODO: fix this issue better.
# Operations should income in order # Operations should income in order
# Then you don't have to do this.. # Then you don't have to do this..
if o.op_number is @operation_counter[o.creator] if o.uid.op_number is @operation_counter[o.uid.creator]
@operation_counter[o.creator]++ @operation_counter[o.uid.creator]++
while @getOperation({creator:o.creator, op_number: @operation_counter[o.creator]})? while @getOperation({creator:o.uid.creator, op_number: @operation_counter[o.uid.creator]})?
@operation_counter[o.creator]++ @operation_counter[o.uid.creator]++
#if @operation_counter[o.creator] isnt (o.op_number + 1) #if @operation_counter[o.uid.creator] isnt (o.uid.op_number + 1)
#console.log (@operation_counter[o.creator] - (o.op_number + 1)) #console.log (@operation_counter[o.uid.creator] - (o.uid.op_number + 1))
#console.log o #console.log o
#throw new Error "You don't receive operations in the proper order. Try counting like this 0,1,2,3,4,.. ;)" #throw new Error "You don't receive operations in the proper order. Try counting like this 0,1,2,3,4,.. ;)"

@ -19,22 +19,14 @@ module.exports = (HB)->
class Operation class Operation
# #
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. # @param {Object} uid A unique identifier.
# @see HistoryBuffer.getNextOperationIdentifier # If uid is undefined, a new uid will be created before at the end of the execution sequence
# #
constructor: (uid)-> constructor: (uid)->
@is_deleted = false @is_deleted = false
@doSync = true
@garbage_collected = false @garbage_collected = false
if not uid? if uid?
uid = HB.getNextOperationIdentifier() @uid = uid
if not uid.doSync?
uid.doSync = not isNaN(parseInt(uid.op_number))
{
'creator': @creator
'op_number' : @op_number
'doSync' : @doSync
} = uid
type: "Insert" type: "Insert"
@ -123,20 +115,28 @@ module.exports = (HB)->
# Computes a unique identifier (uid) that identifies this operation. # Computes a unique identifier (uid) that identifies this operation.
# #
getUid: ()-> getUid: ()->
{ 'creator': @creator, 'op_number': @op_number , 'sync': @doSync} @uid
dontSync: ()-> dontSync: ()->
@doSync = false @doSync = false
# #
# @private # @private
# If not already done, set the uid
# Add this to the HB
# Notify the all the listeners. # Notify the all the listeners.
# #
execute: ()-> execute: ()->
@is_executed = true @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
# is executed (because we need the creator_id)
@uid = HB.getNextOperationIdentifier()
HB.addOperation @
for l in execution_listener for l in execution_listener
l @_encode() l @_encode()
@ @
# #
# @private # @private
@ -261,8 +261,6 @@ module.exports = (HB)->
# @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl) # @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl)
# @param {Operation} next_cl The successor of this operation in the complete-list (cl) # @param {Operation} next_cl The successor of this operation in the complete-list (cl)
# #
# @see HistoryBuffer.getNextOperationIdentifier
#
constructor: (uid, prev_cl, next_cl, origin)-> constructor: (uid, prev_cl, next_cl, origin)->
@saveOperation 'prev_cl', prev_cl @saveOperation 'prev_cl', prev_cl
@saveOperation 'next_cl', next_cl @saveOperation 'next_cl', next_cl
@ -360,7 +358,7 @@ module.exports = (HB)->
# $o happened concurrently # $o happened concurrently
if o.getDistanceToOrigin() is i if o.getDistanceToOrigin() is i
# case 1 # case 1
if o.creator < @creator if o.uid.creator < @uid.creator
@prev_cl = o @prev_cl = o
distance_to_origin = i + 1 distance_to_origin = i + 1
else else
@ -465,8 +463,6 @@ module.exports = (HB)->
# @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl) # @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl)
# @param {Operation} next_cl The successor of this operation in the complete-list (cl) # @param {Operation} next_cl The successor of this operation in the complete-list (cl)
# #
# @see HistoryBuffer.getNextOperationIdentifier
#
constructor: (uid, prev_cl, next_cl, origin)-> constructor: (uid, prev_cl, next_cl, origin)->
@saveOperation 'prev_cl', prev_cl @saveOperation 'prev_cl', prev_cl
@saveOperation 'next_cl', next_cl @saveOperation 'next_cl', next_cl
@ -504,10 +500,10 @@ module.exports = (HB)->
else if @prev_cl? and not @prev_cl.next_cl? else if @prev_cl? and not @prev_cl.next_cl?
delete @prev_cl.unchecked.next_cl delete @prev_cl.unchecked.next_cl
@prev_cl.next_cl = @ @prev_cl.next_cl = @
else if @prev_cl? or @next_cl? else if @prev_cl? or @next_cl? or true # TODO: are you sure? This can happen right?
super super
else #else
throw new Error "Delimiter is unsufficient defined!" # throw new Error "Delimiter is unsufficient defined!"
# #
# @private # @private

@ -98,19 +98,6 @@ module.exports = (HB)->
# #
class JsonType extends types.MapManager class JsonType extends types.MapManager
#
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
# @param {Object} initial_value Create this operation with an initial value.
# @param {String|Boolean} Whether the initial_value should be created as mutable. (Optional - see setMutableDefault)
#
constructor: (uid, initial_value, mutable)->
super uid
if initial_value?
if typeof initial_value isnt "object"
throw new Error "The initial value of JsonTypes must be of type Object! (current type: #{typeof initial_value})"
for name,o of initial_value
@val name, o, mutable
# #
# Identifies this class. # Identifies this class.
# Use it to check whether this is a json-type or something else. # Use it to check whether this is a json-type or something else.
@ -158,7 +145,7 @@ module.exports = (HB)->
# this event is not created by Yatta. # this event is not created by Yatta.
that.val(event.name, event.object[event.name]) that.val(event.name, event.object[event.name])
that.on 'change', (event_name, property_name, op)-> that.on 'change', (event_name, property_name, op)->
if this is that and op.creator isnt HB.getUserId() if this is that and op.uid.creator isnt HB.getUserId()
notifier = Object.getNotifier(that.bound_json) notifier = Object.getNotifier(that.bound_json)
oldVal = that.bound_json[property_name] oldVal = that.bound_json[property_name]
if oldVal? if oldVal?
@ -170,7 +157,7 @@ module.exports = (HB)->
type: 'update' type: 'update'
name: property_name name: property_name
oldValue: oldVal oldValue: oldVal
changed_by: op.creator changed_by: op.uid.creator
else else
notifier.performChange 'add', ()-> notifier.performChange 'add', ()->
that.bound_json[property_name] = that.val(property_name) that.bound_json[property_name] = that.val(property_name)
@ -180,7 +167,7 @@ module.exports = (HB)->
type: 'add' type: 'add'
name: property_name name: property_name
oldValue: oldVal oldValue: oldVal
changed_by: op.creator changed_by: op.uid.creator
@bound_json @bound_json
# #
@ -236,11 +223,13 @@ module.exports = (HB)->
# #
val: (name, content, mutable)-> val: (name, content, mutable)->
if typeof name is 'object' if typeof name is 'object'
# Special case. First argument is an object. Then the second arg is mutable. # 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.. # Keep that in mind when reading the following..
json = new JsonType undefined, name, content jt = new JsonType()
HB.addOperation(json).execute() @replace_manager.replace jt.execute()
@replace_manager.replace json for n,o of name
jt.val n, o, mutable
@ @
else if name? and arguments.length > 1 else if name? and arguments.length > 1
if mutable? if mutable?
@ -253,15 +242,16 @@ module.exports = (HB)->
if typeof content is 'function' if typeof content is 'function'
@ # Just do nothing @ # Just do nothing
else if (not content?) or (((not mutable) or typeof content is 'number') and content.constructor isnt Object) else if (not content?) or (((not mutable) or typeof content is 'number') and content.constructor isnt Object)
obj = HB.addOperation(new types.ImmutableObject undefined, content).execute() super name, (new types.ImmutableObject undefined, content).execute()
super name, obj
else else
if typeof content is 'string' if typeof content is 'string'
word = HB.addOperation(new types.WordType undefined).execute() word = (new types.WordType undefined).execute()
word.insertText 0, content word.insertText 0, content
super name, word super name, word
else if content.constructor is Object else if content.constructor is Object
json = HB.addOperation(new JsonType undefined, content, mutable).execute() json = new JsonType().execute()
for n,o of content
json.val n, o, mutable
super name, json super name, json
else else
throw new Error "You must not set #{typeof content}-types in collaborative Json-objects!" throw new Error "You must not set #{typeof content}-types in collaborative Json-objects!"

@ -34,7 +34,13 @@ module.exports = (HB)->
val: (name, content)-> val: (name, content)->
if content? if content?
if not @map[name]? if not @map[name]?
HB.addOperation(new AddName undefined, @, name).execute() (new AddName undefined, @, name).execute()
## TODO: del this
if @map[name] == null
qqq = @
x = new AddName undefined, @, name
x.execute()
## endtodo
@map[name].replace content @map[name].replace content
@ @
else if name? else if name?
@ -88,16 +94,23 @@ module.exports = (HB)->
if not @validateSavedOperations() if not @validateSavedOperations()
return false return false
else else
uid_r = @map_manager.getUid() # helper for cloning an object
clone = (o)->
p = {}
for name,value of o
p[name] = value
p
uid_r = clone(@map_manager.getUid())
uid_r.doSync = false
uid_r.op_number = "_#{uid_r.op_number}_RM_#{@name}" uid_r.op_number = "_#{uid_r.op_number}_RM_#{@name}"
if not HB.getOperation(uid_r)? if not HB.getOperation(uid_r)?
uid_beg = @map_manager.getUid() uid_beg = clone(uid_r)
uid_beg.op_number = "_#{uid_beg.op_number}_RM_#{@name}_beginning" uid_beg.op_number = "_#{uid_beg.op_number}_RM_#{@name}_beginning"
uid_end = @map_manager.getUid() uid_end = clone(uid_r)
uid_end.op_number = "_#{uid_end.op_number}_RM_#{@name}_end" uid_end.op_number = "_#{uid_end.op_number}_RM_#{@name}_end"
beg = HB.addOperation(new types.Delimiter uid_beg, undefined, uid_end).execute() beg = (new types.Delimiter uid_beg, undefined, uid_end).execute()
end = HB.addOperation(new types.Delimiter uid_end, beg, undefined).execute() end = (new types.Delimiter uid_end, beg, undefined).execute()
@map_manager.map[@name] = HB.addOperation(new ReplaceManager undefined, uid_r, beg, end) @map_manager.map[@name] = new ReplaceManager undefined, uid_r, beg, end
@map_manager.map[@name].setParent @map_manager, @name @map_manager.map[@name].setParent @map_manager, @name
(@map_manager.map[@name].add_name_ops ?= []).push @ (@map_manager.map[@name].add_name_ops ?= []).push @
@map_manager.map[@name].execute() @map_manager.map[@name].execute()
@ -138,8 +151,8 @@ module.exports = (HB)->
@saveOperation 'beginning', beginning @saveOperation 'beginning', beginning
@saveOperation 'end', end @saveOperation 'end', end
else else
@beginning = HB.addOperation new types.Delimiter undefined, undefined, undefined @beginning = new types.Delimiter undefined, undefined, undefined
@end = HB.addOperation new types.Delimiter undefined, @beginning, undefined @end = new types.Delimiter undefined, @beginning, undefined
@beginning.next_cl = @end @beginning.next_cl = @end
@beginning.execute() @beginning.execute()
@end.execute() @end.execute()
@ -240,8 +253,7 @@ module.exports = (HB)->
# #
replace: (content, replaceable_uid)-> replace: (content, replaceable_uid)->
o = @getLastOperation() o = @getLastOperation()
op = new Replaceable content, @, replaceable_uid, o, o.next_cl (new Replaceable content, @, replaceable_uid, o, o.next_cl).execute()
HB.addOperation(op).execute()
undefined undefined
# #

@ -23,7 +23,7 @@ module.exports = (HB)->
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
# #
constructor: (content, uid, prev, next, origin)-> constructor: (content, uid, prev, next, origin)->
if content?.creator? if content?.uid?.creator
@saveOperation 'content', content @saveOperation 'content', content
else else
@content = content @content = content
@ -140,13 +140,10 @@ module.exports = (HB)->
left = left.prev_cl # find the first character to the left, that is not deleted. Case position is 0, its the Delimiter. 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 right = left.next_cl
if content.type? if content.type?
op = new TextInsert content, undefined, left, right (new TextInsert content, undefined, left, right).execute()
HB.addOperation(op).execute()
else else
for c in content for c in content
op = new TextInsert c, undefined, left, right left = (new TextInsert c, undefined, left, right).execute()
HB.addOperation(op).execute()
left = op
@ @
# #
# Inserts a string into the word. # Inserts a string into the word.
@ -171,7 +168,7 @@ module.exports = (HB)->
for i in [0...length] for i in [0...length]
if o instanceof types.Delimiter if o instanceof types.Delimiter
break break
d = HB.addOperation(new TextDelete undefined, o).execute() d = (new TextDelete undefined, o).execute()
o = o.next_cl o = o.next_cl
while not (o instanceof types.Delimiter) and o.isDeleted() while not (o instanceof types.Delimiter) and o.isDeleted()
o = o.next_cl o = o.next_cl
@ -188,7 +185,7 @@ module.exports = (HB)->
# Can only be used if the ReplaceManager was set! # Can only be used if the ReplaceManager was set!
# @see WordType.setReplaceManager # @see WordType.setReplaceManager
if @replace_manager? if @replace_manager?
word = HB.addOperation(new WordType undefined).execute() word = (new WordType undefined).execute()
word.insertText 0, text word.insertText 0, text
@replace_manager.replace(word) @replace_manager.replace(word)
word word

@ -1,8 +1,8 @@
json_types_uninitialized = require "../Types/JsonTypes" json_types_uninitialized = require "./Types/JsonTypes"
HistoryBuffer = require "../HistoryBuffer" HistoryBuffer = require "./HistoryBuffer"
Engine = require "../Engine" Engine = require "./Engine"
adaptConnector = require "../ConnectorAdapter" adaptConnector = require "./ConnectorAdapter"
# #
@ -12,29 +12,28 @@ adaptConnector = require "../ConnectorAdapter"
# * Integer # * Integer
# * Array # * Array
# #
class JsonFramework class Yatta
# #
# @param {String} user_id Unique id of the peer. # @param {String} user_id Unique id of the peer.
# @param {Connector} Connector the connector class. # @param {Connector} Connector the connector class.
# #
constructor: (user_id, @connector)-> constructor: (@connector)->
user_id = @connector.id # TODO: change to getUniqueId()
@HB = new HistoryBuffer user_id @HB = new HistoryBuffer user_id
type_manager = json_types_uninitialized @HB type_manager = json_types_uninitialized @HB
@types = type_manager.types @types = type_manager.types
@engine = new Engine @HB, type_manager.parser @engine = new Engine @HB, type_manager.parser
@HB.engine = @engine # TODO: !! only for debugging @HB.engine = @engine # TODO: !! only for debugging
adaptConnector @connector, @engine, @HB, type_manager.execution_listener adaptConnector @connector, @engine, @HB, type_manager.execution_listener
first_word = new @types.JsonType(@HB.getReservedUniqueIdentifier()) first_word = new @types.JsonType(@HB.getReservedUniqueIdentifier()).execute()
@HB.addOperation(first_word).execute()
uid_beg = @HB.getReservedUniqueIdentifier() uid_beg = @HB.getReservedUniqueIdentifier()
uid_end = @HB.getReservedUniqueIdentifier() uid_end = @HB.getReservedUniqueIdentifier()
beg = @HB.addOperation(new @types.Delimiter uid_beg, undefined, uid_end).execute() beg = (new @types.Delimiter uid_beg, undefined, uid_end).execute()
end = @HB.addOperation(new @types.Delimiter uid_end, beg, undefined).execute() end = (new @types.Delimiter uid_end, beg, undefined).execute()
@root_element = new @types.ReplaceManager undefined, @HB.getReservedUniqueIdentifier(), beg, end @root_element = (new @types.ReplaceManager undefined, @HB.getReservedUniqueIdentifier(), beg, end).execute()
@HB.addOperation(@root_element).execute()
@root_element.replace first_word, @HB.getReservedUniqueIdentifier() @root_element.replace first_word, @HB.getReservedUniqueIdentifier()
# #
@ -64,7 +63,7 @@ class JsonFramework
# #
# Get the UserId from the HistoryBuffer object. # Get the UserId from the HistoryBuffer object.
# In most cases this will be the same as the user_id value with which # In most cases this will be the same as the user_id value with which
# JsonFramework was initialized (Depending on the HistoryBuffer implementation). # Yatta was initialized (Depending on the HistoryBuffer implementation).
# #
getUserId: ()-> getUserId: ()->
@HB.getUserId() @HB.getUserId()
@ -96,7 +95,7 @@ class JsonFramework
# #
# @see JsonType.value # @see JsonType.value
# #
Object.defineProperty JsonFramework.prototype, 'value', Object.defineProperty Yatta.prototype, 'value',
get : -> @getSharedObject().value get : -> @getSharedObject().value
set : (o)-> set : (o)->
if o.constructor is {}.constructor if o.constructor is {}.constructor
@ -105,8 +104,6 @@ class JsonFramework
else else
throw new Error "You must only set Object values!" throw new Error "You must only set Object values!"
module.exports = JsonFramework module.exports = Yatta
if window? if window? and not window.Yatta?
if not window.Y? window.Yatta = Yatta
window.Y = {}
window.Y.JsonFramework = JsonFramework

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

@ -7,14 +7,14 @@ _ = require("underscore")
chai.use(sinonChai) chai.use(sinonChai)
Y = require "../lib/index"
Connector = require "../bower_components/connector/lib/test-connector/test-connector.coffee" Connector = require "../bower_components/connector/lib/test-connector/test-connector.coffee"
Yatta = require "../lib/Yatta.coffee"
Test = require "./TestSuite" Test = require "./TestSuite"
class JsonTest extends Test class JsonTest extends Test
makeNewUser: (user, conn)-> makeNewUser: (user, conn)->
super new Y.JsonFramework user, conn super new Yatta conn
type: "JsonTest" type: "JsonTest"

@ -7,7 +7,6 @@ _ = require("underscore")
chai.use(sinonChai) chai.use(sinonChai)
Y = require "../lib/index"
Connector = require "../bower_components/connector/lib/test-connector/test-connector.coffee" Connector = require "../bower_components/connector/lib/test-connector/test-connector.coffee"
module.exports = class Test module.exports = class Test

1
yatta.js Normal file

File diff suppressed because one or more lines are too long