experimenting with peerjs
This commit is contained in:
		
							parent
							
								
									de399bf7b7
								
							
						
					
					
						commit
						3f5f3cae97
					
				
							
								
								
									
										102
									
								
								build/browser/Connectors/PeerJsConnector.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								build/browser/Connectors/PeerJsConnector.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								build/browser/Connectors/PeerJsConnector.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								build/browser/Connectors/PeerJsConnector.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
!function n(e,t,o){function r(u,c){if(!t[u]){if(!e[u]){var s="function"==typeof require&&require;if(!c&&s)return s(u,!0);if(i)return i(u,!0);throw new Error("Cannot find module '"+u+"'")}var f=t[u]={exports:{}};e[u][0].call(f.exports,function(n){var t=e[u][1][n];return r(t?t:n)},f,f.exports,n,e,t,o)}return t[u].exports}for(var i="function"==typeof require&&require,u=0;u<o.length;u++)r(o[u]);return r}({1:[function(n,e){var t;t=function(n){var e,t;return t=new Peer({key:"h7nlefbgavh1tt9"}),e=function(){function n(n,e,o,r){var i;this.engine=n,this.HB=e,this.execution_listener=o,this.yatta=r,this.peer=t,this.connections=[],this.peer.on("connection",function(n){return function(e){return console.log("received conn"),n.addConnection(e)}}(this)),i=function(n){return function(e){return n.send(e)}}(this),this.execution_listener.push(i)}return n.prototype.connectToPeer=function(n){return this.addConnection(t.connect(n))},n.prototype.addConnection=function(n){var e;return this.connections.push(n),n.on("data",function(n){return function(e){if(console.log("data: "+e),null!=e.HB)return n.engine.applyOpsCheckDouble(e.HB);if(null!=e.op)return n.engine.applyOp(e.op);throw new Error("Can't parse this operation")}}(this)),e=function(e){return function(){return console.log("sending..."),n.send({HB:e.yatta.getHistoryBuffer()._encode()})}}(this),setTimeout(e,1e3)},n.prototype.send=function(n){var e,t,o,r,i;if(n.uid.creator===this.HB.getUserId()&&"string"!=typeof n.uid.op_number){for(console.log("trying to send ops"),r=this.connections,i=[],t=0,o=r.length;o>t;t++)e=r[t],console.log("sent op"),i.push(e.send({op:n}));return i}},n.prototype.receive=function(n){return n.uid.creator!==this.HB.getUserId()?this.engine.applyOp(n):void 0},n}(),t.on("open",function(t){return console.log(t),n(e,t)})},e.exports=t,"undefined"!=typeof window&&null!==window&&(window.createPeerJsConnector=t)},{}]},{},[1]);
 | 
			
		||||
							
								
								
									
										2
									
								
								build/node/Connectors/PeerJsConnector.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								build/node/Connectors/PeerJsConnector.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
(function(){var n;n=function(n){var e,t;return t=new Peer({key:"h7nlefbgavh1tt9"}),e=function(){function n(n,e,o,i){var r;this.engine=n,this.HB=e,this.execution_listener=o,this.yatta=i,this.peer=t,this.connections=[],this.peer.on("connection",function(n){return function(e){return console.log("received conn"),n.addConnection(e)}}(this)),r=function(n){return function(e){return n.send(e)}}(this),this.execution_listener.push(r)}return n.prototype.connectToPeer=function(n){return this.addConnection(t.connect(n))},n.prototype.addConnection=function(n){var e;return this.connections.push(n),n.on("data",function(n){return function(e){if(console.log("data: "+e),null!=e.HB)return n.engine.applyOpsCheckDouble(e.HB);if(null!=e.op)return n.engine.applyOp(e.op);throw new Error("Can't parse this operation")}}(this)),e=function(e){return function(){return console.log("sending..."),n.send({HB:e.yatta.getHistoryBuffer()._encode()})}}(this),setTimeout(e,1e3)},n.prototype.send=function(n){var e,t,o,i,r;if(n.uid.creator===this.HB.getUserId()&&"string"!=typeof n.uid.op_number){for(console.log("trying to send ops"),i=this.connections,r=[],t=0,o=i.length;o>t;t++)e=i[t],console.log("sent op"),r.push(e.send({op:n}));return r}},n.prototype.receive=function(n){return n.uid.creator!==this.HB.getUserId()?this.engine.applyOp(n):void 0},n}(),t.on("open",function(t){return console.log(t),n(e,t)})},module.exports=n,"undefined"!=typeof window&&null!==window&&(window.createPeerJsConnector=n)}).call(this);
 | 
			
		||||
//# sourceMappingURL=../Connectors/PeerJsConnector.js.map
 | 
			
		||||
							
								
								
									
										1
									
								
								build/node/Connectors/PeerJsConnector.js.map
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								build/node/Connectors/PeerJsConnector.js.map
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
{"version":3,"file":"Connectors/PeerJsConnector.js","sources":["Connectors/PeerJsConnector.coffee"],"names":[],"mappings":"CAIA,WAAA,GAAA,EAAA,GAAwB,SAAC,GAEvB,GAAA,GAAA,QAAA,GAAW,GAAA,OAAM,IAAK,oBAKhB,EAAA,WAQS,QAAA,GAAE,EAAS,EAAK,EAAqB,GAEhD,GAAA,EAFY,MAAC,OAAA,EAAQ,KAAC,GAAA,EAAI,KAAC,mBAAA,EAAoB,KAAC,MAAA,EAEhD,KAAC,KAAO,EACR,KAAC,eAED,KAAC,KAAK,GAAG,aAAc,SAAA,SAAA,UAAC,SACtB,SAAQ,IAAI,iBACZ,EAAC,cAAc,KAFM,OAMvB,EAAQ,SAAA,SAAA,UAAC,SACP,GAAC,KAAK,KADA,MAER,KAAC,mBAAmB,KAAK,SAb3B,GAAA,UAeA,cAAe,SAAC,SACd,MAAC,cAAc,EAAK,QAAQ,KAhB9B,EAAA,UAkBA,cAAe,SAAC,GACd,GAAA,SAAA,MAAC,YAAY,KAAK,GAElB,EAAK,GAAG,OAAQ,SAAA,SAAA,UAAC,GAEf,GADA,QAAQ,IAAK,SAAO,GACjB,MAAA,EAAA,SACD,GAAC,OAAO,oBAAoB,EAAK,GAC9B,IAAG,MAAA,EAAA,SACN,GAAC,OAAO,QAAQ,EAAK,GAErB,MAAU,IAAA,OAAM,gCAPJ,OAShB,EAAS,SAAA,SAAA,kBACP,SAAQ,IAAI,cACZ,EAAK,MACH,GAAI,EAAC,MAAM,mBAAmB,cAHzB,MAIT,WAAW,EAAQ,MAlCrB,EAAA,UAwCA,KAAM,SAAC,GACL,GAAA,GAAA,EAAA,EAAA,EAAA,CAAA,IAAG,EAAE,IAAI,UAAW,KAAC,GAAG,aAA6C,gBAA5B,GAAS,IAAI,UAAtD,KACE,QAAQ,IAAI,sBACZ,EAAA,KAAA,YAAA,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,QAAQ,IAAI,WAAZ,EAAA,KACA,EAAK,MACH,GAAI,gBA9CZ,EAAA,UAoDA,QAAS,SAAC,GACR,MAAG,GAAE,IAAI,UAAa,KAAC,GAAG,YACxB,KAAC,OAAO,QAAQ,GADlB,aAGJ,EAAK,GAAG,OAAQ,SAAC,SACf,SAAQ,IAAI,GACZ,EAAS,EAAiB,MAG9B,OAAO,QAAU,8CACjB,OAAQ,sBAAwB","sourcesContent":["\n#\n# @param {Function} callback The callback is called when the connector is initialized.\n#\ncreatePeerJsConnector = (callback)->\n\n  peer = new Peer {key: 'h7nlefbgavh1tt9'}\n\n  #\n  # @see http://peerjs.com\n  #\n  class PeerJsConnector\n\n    #\n    # @param {Engine} engine The transformation engine\n    # @param {HistoryBuffer} HB\n    # @param {Array<Function>} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n    # @param {Yatta} yatta The Yatta framework.\n    #\n    constructor: (@engine, @HB, @execution_listener, @yatta)->\n\n      @peer = peer\n      @connections = []\n\n      @peer.on 'connection', (conn)=>\n        console.log \"received conn\"\n        @addConnection conn\n\n\n\n      send_ = (o)=>\n        @send o\n      @execution_listener.push send_\n\n    connectToPeer: (id)->\n      @addConnection peer.connect id\n\n    addConnection: (conn)->\n      @connections.push conn\n\n      conn.on 'data', (data)=>\n        console.log \"data: #{data}\"\n        if data.HB?\n          @engine.applyOpsCheckDouble data.HB\n        else if data.op?\n          @engine.applyOp data.op\n        else\n          throw new Error \"Can't parse this operation\"\n\n      sendHB = ()=>\n        console.log \"sending...\"\n        conn.send\n          HB: @yatta.getHistoryBuffer()._encode()\n      setTimeout sendHB, 1000\n\n    #\n    # This function is called whenever an operation was executed.\n    # @param {Operation} o The operation that was executed.\n    #\n    send: (o)->\n      if o.uid.creator is @HB.getUserId() and (typeof o.uid.op_number isnt \"string\")\n        console.log \"trying to send ops\"\n        for conn in @connections\n          console.log \"sent op\"\n          conn.send\n            op: o\n\n    #\n    # This function is called whenever an operation was received from another peer.\n    # @param {Operation} o The operation that was received.\n    #\n    receive: (o)->\n      if o.uid.creator isnt @HB.getUserId()\n        @engine.applyOp o\n\n  peer.on 'open', (id)->\n    console.log id\n    callback PeerJsConnector, id\n\n\nmodule.exports = createPeerJsConnector\nwindow?.createPeerJsConnector = createPeerJsConnector\n\n"],"sourceRoot":"/source/"}
 | 
			
		||||
@ -1 +1 @@
 | 
			
		||||
{"version":3,"file":"Types/XmlTypes.js","sources":["Types/XmlTypes.coffee"],"names":[],"mappings":"CA8KkB","sourcesContent":[""],"sourceRoot":"/source/"}
 | 
			
		||||
{"version":3,"file":"Types/XmlTypes.js","sources":["Types/XmlTypes.coffee"],"names":[],"mappings":"CAwFuB","sourcesContent":[""],"sourceRoot":"/source/"}
 | 
			
		||||
@ -9,7 +9,7 @@ First you have to include the following libraries in your widget file:
 | 
			
		||||
<script src="../../build/browser/Connectors/IwcConnector.min.js"></script>
 | 
			
		||||
<script src="./index.js"></script>
 | 
			
		||||
```
 | 
			
		||||
A working widget implementation is maintained [here](./IwcJson.xml) and the js-file is [here](./IwcJson.js)
 | 
			
		||||
A working widget implementation is [IwcJson.xml](./IwcJson.xml) and the js-file is [index.js](./index.js)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								examples/PeerJsJson/PeerJsJson.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								examples/PeerJsJson/PeerJsJson.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
        <meta charset=utf-8 />
 | 
			
		||||
        <title>PeerJs Json Example</title>
 | 
			
		||||
        <script src="http://cdn.peerjs.com/0.3/peer.js"></script>
 | 
			
		||||
        <script src="../../build/browser/Frameworks/JsonYatta.js"></script>
 | 
			
		||||
        <script src="../../build/browser/Connectors/PeerJsConnector.js"></script>
 | 
			
		||||
        <script src="./index.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										177
									
								
								examples/PeerJsJson/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								examples/PeerJsJson/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,177 @@
 | 
			
		||||
## IWC + JSON Example
 | 
			
		||||
Here, I will give a short overview on how to use the IwcJson Framework in Role-SDK widgets.
 | 
			
		||||
First you have to include the following libraries in your widget file:
 | 
			
		||||
```
 | 
			
		||||
<script src="http://open-app.googlecode.com/files/openapp.js"></script>
 | 
			
		||||
<script src="http://dbis.rwth-aachen.de/gadgets/iwc/lib/iwc.js"></script>
 | 
			
		||||
<script src="http://dbis.rwth-aachen.de/~jahns/role-widgets/widgetbundles/libraries/DUIClient.js"></script>
 | 
			
		||||
<script src="../../build/browser/Frameworks/JsonYatta.min.js"></script>
 | 
			
		||||
<script src="../../build/browser/Connectors/PeerJsConnector.min.js"></script>
 | 
			
		||||
<script src="./index.js"></script>
 | 
			
		||||
```
 | 
			
		||||
A working widget implementation is [IwcJson.xml](./IwcJson.xml) and the js-file is [index.js](./index.js)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
function init(){
 | 
			
		||||
    createPeerJsConnector(function(Connector, user_id){
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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 JsonYatta(user_id, Connector);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```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', [1,2,3]);
 | 
			
		||||
      console.log(yatta.val('list')[2] === 3); // true
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
But there is a much more convenient way!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
      console.log(yatta.value.list[2] === 3) // 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
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
window.onload = init
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										130
									
								
								examples/PeerJsJson/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								examples/PeerJsJson/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,130 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 ## IWC + JSON Example
 | 
			
		||||
 Here, I will give a short overview on how to use the IwcJson Framework in Role-SDK widgets.
 | 
			
		||||
 First you have to include the following libraries in your widget file:
 | 
			
		||||
 ```
 | 
			
		||||
<script src="http://open-app.googlecode.com/files/openapp.js"></script>
 | 
			
		||||
<script src="http://dbis.rwth-aachen.de/gadgets/iwc/lib/iwc.js"></script>
 | 
			
		||||
<script src="http://dbis.rwth-aachen.de/~jahns/role-widgets/widgetbundles/libraries/DUIClient.js"></script>
 | 
			
		||||
<script src="../../build/browser/Frameworks/JsonYatta.min.js"></script>
 | 
			
		||||
<script src="../../build/browser/Connectors/PeerJsConnector.min.js"></script>
 | 
			
		||||
<script src="./index.js"></script>
 | 
			
		||||
 ```
 | 
			
		||||
A working widget implementation is [IwcJson.xml](./IwcJson.xml) and the js-file is [index.js](./index.js)
 | 
			
		||||
 */
 | 
			
		||||
function init(){
 | 
			
		||||
    createPeerJsConnector(function(Connector, user_id){
 | 
			
		||||
      /**
 | 
			
		||||
       yatta is the shared json object. If you change something on this object,
 | 
			
		||||
       it will be instantly shared with all the other collaborators.
 | 
			
		||||
      */
 | 
			
		||||
      yatta = new JsonYatta(user_id, Connector);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       Add a integer-property like this
 | 
			
		||||
      */
 | 
			
		||||
      yatta.val('x', 7);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       Get the value of property x like this
 | 
			
		||||
      */
 | 
			
		||||
      console.log(yatta.val('x') === 7); // true
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       A string property can be either mutable or immutable.
 | 
			
		||||
      */
 | 
			
		||||
      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
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       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:
 | 
			
		||||
       */
 | 
			
		||||
      yatta.setMutableDefault('mutable');
 | 
			
		||||
      // or
 | 
			
		||||
      yatta.setMutableDefault('immutable');
 | 
			
		||||
 | 
			
		||||
      yatta.val('new_string', "string");
 | 
			
		||||
      console.log(yatta.val('new_string') === "string"); // true
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       yatta is chainable:
 | 
			
		||||
       */
 | 
			
		||||
      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.
 | 
			
		||||
       */
 | 
			
		||||
      yatta.val('object', {a : {b : "b"}, c : { d : 5 }});
 | 
			
		||||
      console.log(yatta.val('object').val('c').val('d') === 5); // true
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       Lists are always immutable.
 | 
			
		||||
      */
 | 
			
		||||
      yatta.val('list', [1,2,3]);
 | 
			
		||||
      console.log(yatta.val('list')[2] === 3); // true
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       But there is a much more convenient way!
 | 
			
		||||
      */
 | 
			
		||||
      console.log(yatta.value.list[2] === 3) // 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
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       The downside is that you are only allowed to overwrite existing properties.
 | 
			
		||||
      */
 | 
			
		||||
      yatta.value.newProperty = "Awesome"
 | 
			
		||||
      console.log(yatta.value.newProperty !== "Awesome") // true, yatta.value.newProperty is undefined.
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       So, how do we create new properties?
 | 
			
		||||
      */
 | 
			
		||||
      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
 | 
			
		||||
      */
 | 
			
		||||
      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.
 | 
			
		||||
      */
 | 
			
		||||
      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"`.
 | 
			
		||||
      */
 | 
			
		||||
      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)
 | 
			
		||||
      */
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
window.onload = init
 | 
			
		||||
							
								
								
									
										83
									
								
								lib/Connectors/PeerJsConnector.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								lib/Connectors/PeerJsConnector.coffee
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# @param {Function} callback The callback is called when the connector is initialized.
 | 
			
		||||
#
 | 
			
		||||
createPeerJsConnector = (callback)->
 | 
			
		||||
 | 
			
		||||
  peer = new Peer {key: 'h7nlefbgavh1tt9'}
 | 
			
		||||
 | 
			
		||||
  #
 | 
			
		||||
  # @see http://peerjs.com
 | 
			
		||||
  #
 | 
			
		||||
  class PeerJsConnector
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # @param {Engine} engine The transformation engine
 | 
			
		||||
    # @param {HistoryBuffer} HB
 | 
			
		||||
    # @param {Array<Function>} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.
 | 
			
		||||
    # @param {Yatta} yatta The Yatta framework.
 | 
			
		||||
    #
 | 
			
		||||
    constructor: (@engine, @HB, @execution_listener, @yatta)->
 | 
			
		||||
 | 
			
		||||
      @peer = peer
 | 
			
		||||
      @connections = []
 | 
			
		||||
 | 
			
		||||
      @peer.on 'connection', (conn)=>
 | 
			
		||||
        console.log "received conn"
 | 
			
		||||
        @addConnection conn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      send_ = (o)=>
 | 
			
		||||
        @send o
 | 
			
		||||
      @execution_listener.push send_
 | 
			
		||||
 | 
			
		||||
    connectToPeer: (id)->
 | 
			
		||||
      @addConnection peer.connect id
 | 
			
		||||
 | 
			
		||||
    addConnection: (conn)->
 | 
			
		||||
      @connections.push conn
 | 
			
		||||
 | 
			
		||||
      conn.on 'data', (data)=>
 | 
			
		||||
        console.log "data: #{data}"
 | 
			
		||||
        if data.HB?
 | 
			
		||||
          @engine.applyOpsCheckDouble data.HB
 | 
			
		||||
        else if data.op?
 | 
			
		||||
          @engine.applyOp data.op
 | 
			
		||||
        else
 | 
			
		||||
          throw new Error "Can't parse this operation"
 | 
			
		||||
 | 
			
		||||
      sendHB = ()=>
 | 
			
		||||
        console.log "sending..."
 | 
			
		||||
        conn.send
 | 
			
		||||
          HB: @yatta.getHistoryBuffer()._encode()
 | 
			
		||||
      setTimeout sendHB, 1000
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # This function is called whenever an operation was executed.
 | 
			
		||||
    # @param {Operation} o The operation that was executed.
 | 
			
		||||
    #
 | 
			
		||||
    send: (o)->
 | 
			
		||||
      if o.uid.creator is @HB.getUserId() and (typeof o.uid.op_number isnt "string")
 | 
			
		||||
        console.log "trying to send ops"
 | 
			
		||||
        for conn in @connections
 | 
			
		||||
          console.log "sent op"
 | 
			
		||||
          conn.send
 | 
			
		||||
            op: o
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # This function is called whenever an operation was received from another peer.
 | 
			
		||||
    # @param {Operation} o The operation that was received.
 | 
			
		||||
    #
 | 
			
		||||
    receive: (o)->
 | 
			
		||||
      if o.uid.creator isnt @HB.getUserId()
 | 
			
		||||
        @engine.applyOp o
 | 
			
		||||
 | 
			
		||||
  peer.on 'open', (id)->
 | 
			
		||||
    console.log id
 | 
			
		||||
    callback PeerJsConnector, id
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = createPeerJsConnector
 | 
			
		||||
window?.createPeerJsConnector = createPeerJsConnector
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "yatta",
 | 
			
		||||
  "version": "0.0.2",
 | 
			
		||||
  "version": "0.0.3",
 | 
			
		||||
  "description": "A Framework that enables Real-Time Collaboration on arbitrary data structures.",
 | 
			
		||||
  "main": "./build/node/index",
 | 
			
		||||
  "directories": {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user