switched to Gulp
This commit is contained in:
@@ -1,135 +0,0 @@
|
|||||||
"use strict"
|
|
||||||
module.exports = (grunt) ->
|
|
||||||
|
|
||||||
# Project configuration.
|
|
||||||
grunt.initConfig
|
|
||||||
coffee:
|
|
||||||
lib:
|
|
||||||
options:
|
|
||||||
bare: true
|
|
||||||
sourceMap: true
|
|
||||||
expand: true
|
|
||||||
src: ["lib/**/*.coffee"]
|
|
||||||
dest: "dest/"
|
|
||||||
ext: ".js"
|
|
||||||
test:
|
|
||||||
#options:
|
|
||||||
#bare: true
|
|
||||||
expand: true
|
|
||||||
src: ["test/**/*.coffee"]
|
|
||||||
dest: "dest/"
|
|
||||||
ext: ".js"
|
|
||||||
|
|
||||||
watch:
|
|
||||||
lib:
|
|
||||||
files: [
|
|
||||||
"<%= coffee.lib.src %>"
|
|
||||||
]
|
|
||||||
tasks: ["coffee:lib"]
|
|
||||||
test:
|
|
||||||
files: [
|
|
||||||
"<%= coffee.lib.src %>"
|
|
||||||
"<%= coffee.test.src %>"
|
|
||||||
"examples/*"
|
|
||||||
]
|
|
||||||
tasks: ["build"]
|
|
||||||
|
|
||||||
simplemocha:
|
|
||||||
all:
|
|
||||||
src: ['test/**/*.coffee']
|
|
||||||
options:
|
|
||||||
timeout: 9999999
|
|
||||||
ignoreLeaks: false
|
|
||||||
ui: 'bdd'
|
|
||||||
reporter: 'list'
|
|
||||||
compilers: 'coffee:coffee-script'
|
|
||||||
|
|
||||||
pkg: grunt.file.readJSON('package.json')
|
|
||||||
|
|
||||||
coffeelint:
|
|
||||||
app: [
|
|
||||||
'lib/**/*.coffee'
|
|
||||||
'test/**/.coffee'
|
|
||||||
"Gruntfile.coffee"
|
|
||||||
]
|
|
||||||
options:
|
|
||||||
"indentation":
|
|
||||||
"level": "ignore"
|
|
||||||
"no_trailing_whitespace":
|
|
||||||
"level": "warn"
|
|
||||||
"max_line_length":
|
|
||||||
"level": "ignore"
|
|
||||||
#"line_endings":
|
|
||||||
# "level": "error"
|
|
||||||
codo:
|
|
||||||
options:
|
|
||||||
name: "Yatta!"
|
|
||||||
title: "Yatta! Documentation"
|
|
||||||
extras: ["LICENSE.txt", "examples/README.md", "examples/IwcJson.md"]
|
|
||||||
undocumented: yes
|
|
||||||
verbose: false
|
|
||||||
stats: true
|
|
||||||
src: ["./lib"]
|
|
||||||
browserify:
|
|
||||||
dest:
|
|
||||||
files:
|
|
||||||
'dest/browser/test/Yatta_test.js': ['test/**/*.coffee']
|
|
||||||
options:
|
|
||||||
transform: ['coffeeify']
|
|
||||||
debug: true
|
|
||||||
bundleOptions: {debug: true}
|
|
||||||
# Serve files via http-server
|
|
||||||
lib:
|
|
||||||
files:
|
|
||||||
'dest/browser/Frameworks/JsonIwcYatta.js': ['./lib/Frameworks/JsonYatta.coffee', './lib/Connectors/IwcConnector.coffee']
|
|
||||||
options:
|
|
||||||
transform: ['coffeeify']
|
|
||||||
debug: false
|
|
||||||
bundleOptions: {debug: false}
|
|
||||||
uglify:
|
|
||||||
browser:
|
|
||||||
files: [
|
|
||||||
expand: true
|
|
||||||
cwd: './dest/browser/'
|
|
||||||
src: '**/*.js'
|
|
||||||
dest: './dest/browser'
|
|
||||||
ext: '.min.js'
|
|
||||||
]
|
|
||||||
connect:
|
|
||||||
server:
|
|
||||||
options:
|
|
||||||
hostname: '*'
|
|
||||||
port: 1337
|
|
||||||
base: './'
|
|
||||||
keepalive: true
|
|
||||||
middleware: (connect, options, middlewares)->
|
|
||||||
middlewares.push (req, res, next)->
|
|
||||||
if res.header?
|
|
||||||
res.header('Access-Control-Allow-Origin', "*")
|
|
||||||
res.header('Access-Control-Allow-Credentials', true)
|
|
||||||
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
|
|
||||||
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
|
|
||||||
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0')
|
|
||||||
return next()
|
|
||||||
return middlewares
|
|
||||||
literate:
|
|
||||||
"examples/IwcJson.md": "examples/IwcJson.js"
|
|
||||||
options:
|
|
||||||
code: true
|
|
||||||
|
|
||||||
# These plugins provide necessary tasks.
|
|
||||||
grunt.loadNpmTasks "grunt-browserify"
|
|
||||||
grunt.loadNpmTasks "grunt-contrib-uglify"
|
|
||||||
grunt.loadNpmTasks "grunt-contrib-coffee"
|
|
||||||
grunt.loadNpmTasks 'grunt-contrib-connect'
|
|
||||||
grunt.loadNpmTasks "grunt-contrib-watch"
|
|
||||||
grunt.loadNpmTasks "grunt-literate"
|
|
||||||
grunt.loadNpmTasks "grunt-simple-mocha"
|
|
||||||
grunt.loadNpmTasks "grunt-coffeelint"
|
|
||||||
grunt.loadNpmTasks "grunt-codo"
|
|
||||||
|
|
||||||
grunt.registerTask "build", ["coffeelint", "codo", "browserify", "test"]
|
|
||||||
grunt.registerTask "production", ["test", "coffee","coffeelint", "literate", "browserify", "uglify", "codo"]
|
|
||||||
grunt.registerTask "default", ["build", "watch"]
|
|
||||||
grunt.registerTask "production", ["coffee"]
|
|
||||||
grunt.registerTask "test", ["simplemocha"]
|
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014 Kevin Jahns.
|
Copyright (c) 2014 Kevin Jahns <kevin.jahns@rwth-aachen.de>.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
||||||
],
|
],
|
||||||
"description": "A Framework that enables Real-Time Collaboration on arbitrary data structures.",
|
"description": "A Framework that enables Real-Time Collaboration on arbitrary data structures.",
|
||||||
"main": "./dest/browser/**",
|
"main": "./build/browser/**",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"OT",
|
"OT",
|
||||||
"collaboration",
|
"collaboration",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
!function t(n,e,r){function i(u,a){if(!e[u]){if(!n[u]){var c="function"==typeof require&&require;if(!a&&c)return c(u,!0);if(o)return o(u,!0);throw new Error("Cannot find module '"+u+"'")}var s=e[u]={exports:{}};n[u][0].call(s.exports,function(t){var e=n[u][1][t];return i(e?e:t)},s,s.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){var n,e,r,i,o,u;return o={},e=new DUIClient,e.connect(function(t){var n;return null!=(n=o[t.action])?n.map(function(n){return setTimeout(function(){return n(t)},0)}):void 0}),e.initOK(),u=null,n=function(){function t(t,n,r,i){var a,c,s;this.engine=t,this.HB=n,this.execution_listener=r,this.yatta=i,this.duiClient=e,this.iwcHandler=o,s=function(t){return function(n){return t.send(n)}}(this),this.execution_listener.push(s),a=function(t){return function(n){var e;return e=n.extras,t.receive(e)}}(this),this.iwcHandler.Yatta_new_operation=[a],null!=u&&this.engine.applyOpsCheckDouble(u),c=function(t){return function(){var n;return n={HB:t.yatta.getHistoryBuffer()._encode()},t.sendIwcIntent("Yatta_push_HB_element",n)}}(this),this.iwcHandler.Yatta_get_HB_element=[c]}return 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.prototype.sendIwcIntent=function(t,n){var e;return e={action:t,component:"",data:"",dataType:"",extras:n},this.duiClient.sendIntent(e)},t}(),r={action:"Yatta_get_HB_element",component:"",data:"",dataType:"",extras:{}},i=function(){var i,a;return e.sendIntent(r),i=!1,a=function(r){var o;return o=e.getIwcClient()._componentName,u=null!=r?r.extras.HB:void 0,i?void 0:(i=!0,t(n,o))},o.Yatta_push_HB_element=[a],setTimeout(a,0)},void setTimeout(i,0*Math.random())},n.exports=e,"undefined"!=typeof window&&null!==window&&(window.createConnector=e)},{}]},{},[1]);
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
!function r(e,t,o){function p(s,i){if(!t[s]){if(!e[s]){var u="function"==typeof require&&require;if(!i&&u)return u(s,!0);if(n)return n(s,!0);throw new Error("Cannot find module '"+s+"'")}var h=t[s]={exports:{}};e[s][0].call(h.exports,function(r){var t=e[s][1][r];return p(t?t:r)},h,h.exports,r,e,t,o)}return t[s].exports}for(var n="function"==typeof require&&require,s=0;s<o.length;s++)p(o[s]);return p}({1:[function(r,e){var t;t=function(){function r(r,e){this.HB=r,this.parser=e,this.unprocessed_ops=[]}return r.prototype.parseOperation=function(r){var e;if(e=this.parser[r.type],null!=e)return e(r);throw new Error("You forgot to specify a parser for type "+r.type+". The message is "+JSON.stringify(r)+".")},r.prototype.applyOpsBundle=function(r){var e,t,o,p,n,s,i,u;for(t=[],o=0,s=r.length;s>o;o++)e=r[o],t.push(this.parseOperation(e));for(p=0,i=t.length;i>p;p++)e=t[p],this.HB.addOperation(e);for(n=0,u=t.length;u>n;n++)e=t[n],e.execute()||this.unprocessed_ops.push(e);return this.tryUnprocessed()},r.prototype.applyOpsCheckDouble=function(r){var e,t,o,p;for(p=[],t=0,o=r.length;o>t;t++)e=r[t],p.push(null!=this.HB.getOperation(e.uid)?this.applyOp(e):void 0);return p},r.prototype.applyOps=function(r){var e,t,o,p;for(p=[],t=0,o=r.length;o>t;t++)e=r[t],p.push(this.applyOp(e));return p},r.prototype.applyOp=function(r){var e;return e=this.parseOperation(r),this.HB.addToCounter(e),e.execute()?this.HB.addOperation(e):this.unprocessed_ops.push(e),this.tryUnprocessed()},r.prototype.tryUnprocessed=function(){var r,e,t,o,p,n,s;for(s=[];;){for(r=this.unprocessed_ops.length,t=[],n=this.unprocessed_ops,o=0,p=n.length;p>o;o++)e=n[o],e.execute()?this.HB.addOperation(e):t.push(e);if(this.unprocessed_ops=t,this.unprocessed_ops.length===r)break;s.push(void 0)}return s},r}(),e.exports=t},{}]},{},[1]);
|
||||||
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
!function r(e,t,n){function o(u,f){if(!t[u]){if(!e[u]){var p="function"==typeof require&&require;if(!f&&p)return p(u,!0);if(i)return i(u,!0);throw new Error("Cannot find module '"+u+"'")}var c=t[u]={exports:{}};e[u][0].call(c.exports,function(r){var t=e[u][1][r];return o(t?t:r)},c,c.exports,r,e,t,n)}return t[u].exports}for(var i="function"==typeof require&&require,u=0;u<n.length;u++)o(n[u]);return o}({1:[function(r,e){var t;t=function(){function r(r){this.user_id=r,this.operation_counter={},this.buffer={},this.change_listeners=[]}return r.prototype.getUserId=function(){return this.user_id},r.prototype.getReservedUniqueIdentifier=function(){return{creator:"_",op_number:"_"}},r.prototype.getOperationCounter=function(){var r,e,t,n;e={},n=this.operation_counter;for(t in n)r=n[t],e[t]=r;return e},r.prototype._encode=function(r){var e,t,n,o,i,u,f,p,c,a;null==r&&(r={}),e=[],p=function(e,t){if(null==e||null==t)throw new Error("dah!");return null==r[e]||r[e]<=t},a=this.buffer;for(f in a){c=a[f];for(i in c)if(t=c[i],!isNaN(parseInt(i))&&p(f,i)){if(n=t._encode(),null!=t.next_cl){for(o=t.next_cl;null!=o.next_cl&&p(o.creator,o.op_number);)o=o.next_cl;n.next=o.getUid()}else if(null!=t.prev_cl){for(u=t.prev_cl;null!=u.prev_cl&&p(o.creator,o.op_number);)u=u.prev_cl;n.prev=u.getUid()}e.push(n)}}return e},r.prototype.getNextOperationIdentifier=function(r){var e;return null==r&&(r=this.user_id),null==this.operation_counter[r]&&(this.operation_counter[r]=0),e={creator:r,op_number:this.operation_counter[r]},this.operation_counter[r]++,e},r.prototype.getOperation=function(r){var e;if(r instanceof Object)return null!=(e=this.buffer[r.creator])?e[r.op_number]:void 0;if(null!=r)throw new Error("This type of uid is not defined!")},r.prototype.addOperation=function(r){if(null==this.buffer[r.creator]&&(this.buffer[r.creator]={}),null!=this.buffer[r.creator][r.op_number])throw new Error("You must not overwrite operations!");return this.buffer[r.creator][r.op_number]=r,r},r.prototype.addToCounter=function(r){return null==this.operation_counter[r.creator]&&(this.operation_counter[r.creator]=0),"number"==typeof r.op_number&&r.creator!==this.getUserId()?this.operation_counter[r.creator]++:void 0},r}(),e.exports=t},{}]},{},[1]);
|
||||||
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
|||||||
|
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},{}]},{},[1])
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL1R5cGVzL1htbFR5cGVzLmNvZmZlZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpfXZhciBmPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChmLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGYsZi5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJcblxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKbWFXeGxJam9pTDJodmJXVXZaRzF2Ym1Ga0wwUnliM0JpYjNndldXRjBkR0VoTDJ4cFlpOVVlWEJsY3k5WWJXeFVlWEJsY3k1amIyWm1aV1VpTENKemIzVnlZMlZTYjI5MElqb2lJaXdpYzI5MWNtTmxjeUk2V3lJdmFHOXRaUzlrYlc5dVlXUXZSSEp2Y0dKdmVDOVpZWFIwWVNFdmJHbGlMMVI1Y0dWekwxaHRiRlI1Y0dWekxtTnZabVpsWlNKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGcllrY2lMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUlpWFgwPSJdfQ==
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
!function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);throw new Error("Cannot find module '"+i+"'")}var a=n[i]={exports:{}};e[i][0].call(a.exports,function(r){var n=e[i][1][r];return o(n?n:r)},a,a.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(){},{}]},{},[1]);
|
||||||
File diff suppressed because one or more lines are too long
Vendored
+2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,112 @@
|
|||||||
|
|
||||||
|
#
|
||||||
|
# @param {Function} callback The callback is called when the connector is initialized.
|
||||||
|
#
|
||||||
|
createIwcConnector = (callback)->
|
||||||
|
iwcHandler = {}
|
||||||
|
duiClient = new DUIClient()
|
||||||
|
#@duiClient = new iwc.Client()
|
||||||
|
duiClient.connect (intent)->
|
||||||
|
#console.log "intent received iwc: #{JSON.stringify(intent)}"
|
||||||
|
#console.log "#{JSON.stringify(@iwcHandler)}"
|
||||||
|
iwcHandler[intent.action]?.map (f)->
|
||||||
|
setTimeout ()->
|
||||||
|
f intent
|
||||||
|
, 0
|
||||||
|
|
||||||
|
duiClient.initOK()
|
||||||
|
|
||||||
|
received_HB = null
|
||||||
|
|
||||||
|
#
|
||||||
|
# The Iwc Connector adds support for the Inter-Widget-Communication protocol that is used in the Role-SDK.
|
||||||
|
# @see http://dbis.rwth-aachen.de/cms/projects/the-xmpp-experience#interwidget-communication
|
||||||
|
# @see http://dbis.rwth-aachen.de/cms/projects/ROLE
|
||||||
|
#
|
||||||
|
class IwcConnector
|
||||||
|
|
||||||
|
#
|
||||||
|
# @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)->
|
||||||
|
@duiClient = duiClient
|
||||||
|
@iwcHandler = iwcHandler
|
||||||
|
|
||||||
|
send_ = (o)=>
|
||||||
|
@send o
|
||||||
|
@execution_listener.push send_
|
||||||
|
|
||||||
|
receive_ = (intent)=>
|
||||||
|
o = intent.extras
|
||||||
|
@receive o
|
||||||
|
@iwcHandler["Yatta_new_operation"] = [receive_]
|
||||||
|
|
||||||
|
if received_HB?
|
||||||
|
@engine.applyOpsCheckDouble received_HB
|
||||||
|
|
||||||
|
sendHistoryBuffer = ()=>
|
||||||
|
json =
|
||||||
|
HB : @yatta.getHistoryBuffer()._encode()
|
||||||
|
@sendIwcIntent "Yatta_push_HB_element", json
|
||||||
|
@iwcHandler["Yatta_get_HB_element"] = [sendHistoryBuffer]
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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")
|
||||||
|
@sendIwcIntent "Yatta_new_operation", 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
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper for sending iwc intents.
|
||||||
|
# @param {String} action_name The name of the action that is going to be send.
|
||||||
|
# @param {String} content The content that is atteched to the intent.
|
||||||
|
#
|
||||||
|
sendIwcIntent: (action_name, content)->
|
||||||
|
intent =
|
||||||
|
action: action_name
|
||||||
|
component: ""
|
||||||
|
data: ""
|
||||||
|
dataType: ""
|
||||||
|
extras: content
|
||||||
|
|
||||||
|
@duiClient.sendIntent(intent)
|
||||||
|
|
||||||
|
get_HB_intent =
|
||||||
|
action: "Yatta_get_HB_element"
|
||||||
|
component: ""
|
||||||
|
data: ""
|
||||||
|
dataType: ""
|
||||||
|
extras: {}
|
||||||
|
|
||||||
|
init = ()->
|
||||||
|
duiClient.sendIntent(get_HB_intent)
|
||||||
|
|
||||||
|
is_initialized = false
|
||||||
|
receiveHB = (json)->
|
||||||
|
proposed_user_id = duiClient.getIwcClient()._componentName
|
||||||
|
received_HB = json?.extras.HB
|
||||||
|
if not is_initialized
|
||||||
|
is_initialized = true
|
||||||
|
callback IwcConnector, proposed_user_id
|
||||||
|
iwcHandler["Yatta_push_HB_element"] = [receiveHB]
|
||||||
|
setTimeout receiveHB, 0
|
||||||
|
|
||||||
|
setTimeout init, (Math.random()*0)
|
||||||
|
|
||||||
|
undefined
|
||||||
|
module.exports = createIwcConnector
|
||||||
|
window?.createConnector = createIwcConnector
|
||||||
|
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Connectors/IwcConnector.coffee","names":[],"mappings":"","sources":["Connectors/IwcConnector.coffee"],"sourcesContent":["\n#\n# @param {Function} callback The callback is called when the connector is initialized.\n#\ncreateIwcConnector = (callback)->\n iwcHandler = {}\n duiClient = new DUIClient()\n #@duiClient = new iwc.Client()\n duiClient.connect (intent)->\n #console.log \"intent received iwc: #{JSON.stringify(intent)}\"\n #console.log \"#{JSON.stringify(@iwcHandler)}\"\n iwcHandler[intent.action]?.map (f)->\n setTimeout ()->\n f intent\n , 0\n\n duiClient.initOK()\n\n received_HB = null\n\n #\n # The Iwc Connector adds support for the Inter-Widget-Communication protocol that is used in the Role-SDK.\n # @see http://dbis.rwth-aachen.de/cms/projects/the-xmpp-experience#interwidget-communication\n # @see http://dbis.rwth-aachen.de/cms/projects/ROLE\n #\n class IwcConnector\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 @duiClient = duiClient\n @iwcHandler = iwcHandler\n\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n receive_ = (intent)=>\n o = intent.extras\n @receive o\n @iwcHandler[\"Yatta_new_operation\"] = [receive_]\n\n if received_HB?\n @engine.applyOpsCheckDouble received_HB\n\n sendHistoryBuffer = ()=>\n json =\n HB : @yatta.getHistoryBuffer()._encode()\n @sendIwcIntent \"Yatta_push_HB_element\", json\n @iwcHandler[\"Yatta_get_HB_element\"] = [sendHistoryBuffer]\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 @sendIwcIntent \"Yatta_new_operation\", 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 #\n # Helper for sending iwc intents.\n # @param {String} action_name The name of the action that is going to be send.\n # @param {String} content The content that is atteched to the intent.\n #\n sendIwcIntent: (action_name, content)->\n intent =\n action: action_name\n component: \"\"\n data: \"\"\n dataType: \"\"\n extras: content\n\n @duiClient.sendIntent(intent)\n\n get_HB_intent =\n action: \"Yatta_get_HB_element\"\n component: \"\"\n data: \"\"\n dataType: \"\"\n extras: {}\n\n init = ()->\n duiClient.sendIntent(get_HB_intent)\n\n is_initialized = false\n receiveHB = (json)->\n proposed_user_id = duiClient.getIwcClient()._componentName\n received_HB = json?.extras.HB\n if not is_initialized\n is_initialized = true\n callback IwcConnector, proposed_user_id\n iwcHandler[\"Yatta_push_HB_element\"] = [receiveHB]\n setTimeout receiveHB, 0\n\n setTimeout init, (Math.random()*0)\n\n undefined\nmodule.exports = createIwcConnector\nwindow?.createConnector = createIwcConnector\n\n"],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var t;t=function(t){var n,e,i,r,o,u;return o={},e=new DUIClient,e.connect(function(t){var n;return null!=(n=o[t.action])?n.map(function(n){return setTimeout(function(){return n(t)},0)}):void 0}),e.initOK(),u=null,n=function(){function t(t,n,i,r){var a,c,s;this.engine=t,this.HB=n,this.execution_listener=i,this.yatta=r,this.duiClient=e,this.iwcHandler=o,s=function(t){return function(n){return t.send(n)}}(this),this.execution_listener.push(s),a=function(t){return function(n){var e;return e=n.extras,t.receive(e)}}(this),this.iwcHandler.Yatta_new_operation=[a],null!=u&&this.engine.applyOpsCheckDouble(u),c=function(t){return function(){var n;return n={HB:t.yatta.getHistoryBuffer()._encode()},t.sendIwcIntent("Yatta_push_HB_element",n)}}(this),this.iwcHandler.Yatta_get_HB_element=[c]}return 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.prototype.sendIwcIntent=function(t,n){var e;return e={action:t,component:"",data:"",dataType:"",extras:n},this.duiClient.sendIntent(e)},t}(),i={action:"Yatta_get_HB_element",component:"",data:"",dataType:"",extras:{}},r=function(){var r,a;return e.sendIntent(i),r=!1,a=function(i){var o;return o=e.getIwcClient()._componentName,u=null!=i?i.extras.HB:void 0,r?void 0:(r=!0,t(n,o))},o.Yatta_push_HB_element=[a],setTimeout(a,0)},void setTimeout(r,0*Math.random())},module.exports=t,"undefined"!=typeof window&&null!==window&&(window.createConnector=t)}).call(this);
|
||||||
|
//# sourceMappingURL=../Connectors/IwcConnector.js.map
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Connectors/IwcConnector.js","sources":["Connectors/IwcConnector.coffee"],"names":[],"mappings":"CAIA,WAAA,GAAA,EAAA,GAAqB,SAAC,GACpB,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,QAAA,MACA,EAAgB,GAAA,WAEhB,EAAU,QAAQ,SAAC,GAGjB,GAAA,kCAA2B,IAAI,SAAC,SAC9B,YAAW,iBACT,GAAE,IACF,KAHJ,SAKF,EAAU,SAEV,EAAc,KAOR,EAAA,WAQS,QAAA,GAAE,EAAS,EAAK,EAAqB,GAChD,GAAA,GAAA,EAAA,CADY,MAAC,OAAA,EAAQ,KAAC,GAAA,EAAI,KAAC,mBAAA,EAAoB,KAAC,MAAA,EAChD,KAAC,UAAY,EACb,KAAC,WAAa,EAEd,EAAQ,SAAA,SAAA,UAAC,SACP,GAAC,KAAK,KADA,MAER,KAAC,mBAAmB,KAAK,GAEzB,EAAW,SAAA,SAAA,UAAC,GACV,GAAA,SAAA,GAAI,EAAO,OACX,EAAC,QAAQ,KAFA,MAGX,KAAC,WAAW,qBAA0B,GAEnC,MAAA,GACD,KAAC,OAAO,oBAAoB,GAE9B,EAAoB,SAAA,SAAA,YAClB,GAAA,SAAA,IACE,GAAK,EAAC,MAAM,mBAAmB,WACjC,EAAC,cAAc,wBAAyB,KAHtB,MAIpB,KAAC,WAAW,sBAA2B,SApBzC,GAAA,UA0BA,KAAM,SAAC,GACL,MAAG,GAAE,IAAI,UAAW,KAAC,GAAG,aAA6C,gBAA5B,GAAS,IAAI,UACpD,KAAC,cAAc,sBAAuB,GADxC,QA3BF,EAAA,UAkCA,QAAS,SAAC,GACR,MAAG,GAAE,IAAI,UAAa,KAAC,GAAG,YACxB,KAAC,OAAO,QAAQ,GADlB,QAnCF,EAAA,UA2CA,cAAe,SAAC,EAAa,GAC3B,GAAA,SAAA,IACE,OAAQ,EACR,UAAW,GACX,KAAM,GACN,SAAU,GACV,OAAQ,GAEV,KAAC,UAAU,WAAW,SAE1B,GACE,OAAQ,uBACR,UAAW,GACX,KAAM,GACN,SAAU,GACV,WAEF,EAAO,WACL,GAAA,GAAA,QAAA,GAAU,WAAW,GAErB,GAAiB,EACjB,EAAY,SAAC,GACX,GAAA,EAEA,OAFA,GAAmB,EAAU,eAAe,eAC5C,EAAA,MAAA,EAAc,EAAM,OAAO,GAAA,OACxB,EAAH,QACE,GAAiB,EACjB,EAAS,EAAc,KAC3B,EAAW,uBAA4B,GACvC,WAAW,EAAW,QAExB,YAAW,EAAqB,EAAd,KAAK,WAGzB,OAAO,QAAU,8CACjB,OAAQ,gBAAkB","sourcesContent":["\n#\n# @param {Function} callback The callback is called when the connector is initialized.\n#\ncreateIwcConnector = (callback)->\n iwcHandler = {}\n duiClient = new DUIClient()\n #@duiClient = new iwc.Client()\n duiClient.connect (intent)->\n #console.log \"intent received iwc: #{JSON.stringify(intent)}\"\n #console.log \"#{JSON.stringify(@iwcHandler)}\"\n iwcHandler[intent.action]?.map (f)->\n setTimeout ()->\n f intent\n , 0\n\n duiClient.initOK()\n\n received_HB = null\n\n #\n # The Iwc Connector adds support for the Inter-Widget-Communication protocol that is used in the Role-SDK.\n # @see http://dbis.rwth-aachen.de/cms/projects/the-xmpp-experience#interwidget-communication\n # @see http://dbis.rwth-aachen.de/cms/projects/ROLE\n #\n class IwcConnector\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 @duiClient = duiClient\n @iwcHandler = iwcHandler\n\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n receive_ = (intent)=>\n o = intent.extras\n @receive o\n @iwcHandler[\"Yatta_new_operation\"] = [receive_]\n\n if received_HB?\n @engine.applyOpsCheckDouble received_HB\n\n sendHistoryBuffer = ()=>\n json =\n HB : @yatta.getHistoryBuffer()._encode()\n @sendIwcIntent \"Yatta_push_HB_element\", json\n @iwcHandler[\"Yatta_get_HB_element\"] = [sendHistoryBuffer]\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 @sendIwcIntent \"Yatta_new_operation\", 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 #\n # Helper for sending iwc intents.\n # @param {String} action_name The name of the action that is going to be send.\n # @param {String} content The content that is atteched to the intent.\n #\n sendIwcIntent: (action_name, content)->\n intent =\n action: action_name\n component: \"\"\n data: \"\"\n dataType: \"\"\n extras: content\n\n @duiClient.sendIntent(intent)\n\n get_HB_intent =\n action: \"Yatta_get_HB_element\"\n component: \"\"\n data: \"\"\n dataType: \"\"\n extras: {}\n\n init = ()->\n duiClient.sendIntent(get_HB_intent)\n\n is_initialized = false\n receiveHB = (json)->\n proposed_user_id = duiClient.getIwcClient()._componentName\n received_HB = json?.extras.HB\n if not is_initialized\n is_initialized = true\n callback IwcConnector, proposed_user_id\n iwcHandler[\"Yatta_push_HB_element\"] = [receiveHB]\n setTimeout receiveHB, 0\n\n setTimeout init, (Math.random()*0)\n\n undefined\nmodule.exports = createIwcConnector\nwindow?.createConnector = createIwcConnector\n\n"],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
_ = require "underscore"
|
||||||
|
|
||||||
|
module.exports = (user_list)->
|
||||||
|
|
||||||
|
#
|
||||||
|
# A trivial Connector that simulates network delay.
|
||||||
|
#
|
||||||
|
class TestConnector
|
||||||
|
|
||||||
|
#
|
||||||
|
# @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)->
|
||||||
|
send_ = (o)=>
|
||||||
|
@send o
|
||||||
|
@execution_listener.push send_
|
||||||
|
|
||||||
|
@applied_operations = []
|
||||||
|
appliedOperationsListener = (o)=>
|
||||||
|
@applied_operations.push o
|
||||||
|
@execution_listener.push appliedOperationsListener
|
||||||
|
if not (user_list?.length is 0)
|
||||||
|
@engine.applyOps user_list[0].getHistoryBuffer()._encode()
|
||||||
|
|
||||||
|
@unexecuted = {}
|
||||||
|
|
||||||
|
#
|
||||||
|
# This engine applied operations in a specific order.
|
||||||
|
# Get the ops in the right order.
|
||||||
|
#
|
||||||
|
getOpsInExecutionOrder: ()->
|
||||||
|
@applied_operations
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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")
|
||||||
|
for user in user_list
|
||||||
|
if user.getUserId() isnt @HB.getUserId()
|
||||||
|
user.getConnector().receive(o)
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function is called whenever an operation was received from another peer.
|
||||||
|
# @param {Operation} o The operation that was received.
|
||||||
|
#
|
||||||
|
receive: (o)->
|
||||||
|
@unexecuted[o.uid.creator] ?= []
|
||||||
|
@unexecuted[o.uid.creator].push o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flush one operation from the line of a specific user.
|
||||||
|
#
|
||||||
|
flushOne: (user)->
|
||||||
|
if @unexecuted[user]?.length > 0
|
||||||
|
@engine.applyOp @unexecuted[user].shift()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flush one operation on a random line.
|
||||||
|
#
|
||||||
|
flushOneRandom: ()->
|
||||||
|
@flushOne (_.random 0, (user_list.length-1))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flush all operations on every line.
|
||||||
|
#
|
||||||
|
flushAll: ()->
|
||||||
|
for n,ops of @unexecuted
|
||||||
|
@engine.applyOps ops
|
||||||
|
@unexecuted = {}
|
||||||
|
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Connectors/TestConnector.coffee","names":[],"mappings":"","sources":["Connectors/TestConnector.coffee"],"sourcesContent":["\n_ = require \"underscore\"\n\nmodule.exports = (user_list)->\n\n #\n # A trivial Connector that simulates network delay.\n #\n class TestConnector\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)->\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n @applied_operations = []\n appliedOperationsListener = (o)=>\n @applied_operations.push o\n @execution_listener.push appliedOperationsListener\n if not (user_list?.length is 0)\n @engine.applyOps user_list[0].getHistoryBuffer()._encode()\n\n @unexecuted = {}\n\n #\n # This engine applied operations in a specific order.\n # Get the ops in the right order.\n #\n getOpsInExecutionOrder: ()->\n @applied_operations\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 for user in user_list\n if user.getUserId() isnt @HB.getUserId()\n user.getConnector().receive(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 @unexecuted[o.uid.creator] ?= []\n @unexecuted[o.uid.creator].push o\n\n #\n # Flush one operation from the line of a specific user.\n #\n flushOne: (user)->\n if @unexecuted[user]?.length > 0\n @engine.applyOp @unexecuted[user].shift()\n\n #\n # Flush one operation on a random line.\n #\n flushOneRandom: ()->\n @flushOne (_.random 0, (user_list.length-1))\n\n #\n # Flush all operations on every line.\n #\n flushAll: ()->\n for n,ops of @unexecuted\n @engine.applyOps ops\n @unexecuted = {}\n\n"],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var e;e=require("underscore"),module.exports=function(t){var n;return n=function(){function n(e,n,i){var r,u;this.engine=e,this.HB=n,this.execution_listener=i,u=function(e){return function(t){return e.send(t)}}(this),this.execution_listener.push(u),this.applied_operations=[],r=function(e){return function(t){return e.applied_operations.push(t)}}(this),this.execution_listener.push(r),0!==(null!=t?t.length:void 0)&&this.engine.applyOps(t[0].getHistoryBuffer()._encode()),this.unexecuted={}}return n.prototype.getOpsInExecutionOrder=function(){return this.applied_operations},n.prototype.send=function(e){var n,i,r,u;if(e.uid.creator===this.HB.getUserId()&&"string"!=typeof e.uid.op_number){for(u=[],i=0,r=t.length;r>i;i++)n=t[i],u.push(n.getUserId()!==this.HB.getUserId()?n.getConnector().receive(e):void 0);return u}},n.prototype.receive=function(e){var t,n;return null==(t=this.unexecuted)[n=e.uid.creator]&&(t[n]=[]),this.unexecuted[e.uid.creator].push(e)},n.prototype.flushOne=function(e){var t;return(null!=(t=this.unexecuted[e])?t.length:void 0)>0?this.engine.applyOp(this.unexecuted[e].shift()):void 0},n.prototype.flushOneRandom=function(){return this.flushOne(e.random(0,t.length-1))},n.prototype.flushAll=function(){var e,t,n;n=this.unexecuted;for(e in n)t=n[e],this.engine.applyOps(t);return this.unexecuted={}},n}()}}).call(this);
|
||||||
|
//# sourceMappingURL=../Connectors/TestConnector.js.map
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Connectors/TestConnector.js","sources":["Connectors/TestConnector.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,EAAA,GAAI,QAAQ,cAEZ,OAAO,QAAU,SAAC,GAKhB,GAAA,SAAM,GAAA,WAQS,QAAA,GAAE,EAAS,EAAK,GAC3B,GAAA,GAAA,CADY,MAAC,OAAA,EAAQ,KAAC,GAAA,EAAI,KAAC,mBAAA,EAC3B,EAAQ,SAAA,SAAA,UAAC,SACP,GAAC,KAAK,KADA,MAER,KAAC,mBAAmB,KAAK,GAEzB,KAAC,sBACD,EAA4B,SAAA,SAAA,UAAC,SAC3B,GAAC,mBAAmB,KAAK,KADC,MAE5B,KAAC,mBAAmB,KAAK,GACI,KAA1B,MAAA,EAAK,EAAW,OAAA,SACjB,KAAC,OAAO,SAAS,EAAU,GAAG,mBAAmB,WAEnD,KAAC,oBAZH,GAAA,UAkBA,uBAAwB,iBACtB,MAAC,oBAnBH,EAAA,UAyBA,KAAM,SAAC,GACL,GAAA,GAAA,EAAA,EAAA,CAAA,IAAI,EAAE,IAAI,UAAW,KAAC,GAAG,aAA8C,gBAA5B,GAAS,IAAI,UAAxD,KACE,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,kBACK,EAAK,cAAiB,KAAC,GAAG,YAC3B,EAAK,eAAe,QAAQ,sBA7BpC,EAAA,UAmCA,QAAS,SAAC,GACR,GAAA,GAAA,+DACA,KAAC,WAAW,EAAE,IAAI,SAAS,KAAK,IArClC,EAAA,UA0CA,SAAU,SAAC,GACT,GAAA,EAAA,QAAA,OAAA,EAAA,KAAA,WAAA,IAAA,EAAsB,OAAA,QAAS,EAC7B,KAAC,OAAO,QAAQ,KAAC,WAAW,GAAM,SADpC,QA3CF,EAAA,UAiDA,eAAgB,iBACd,MAAC,SAAU,EAAE,OAAO,EAAI,EAAU,OAAO,KAlD3C,EAAA,UAuDA,SAAU,WACR,GAAA,GAAA,EAAA,CAAA,GAAA,KAAA,UAAA,KAAA,IAAA,UACE,KAAC,OAAO,SAAS,SACnB,MAAC","sourcesContent":["\n_ = require \"underscore\"\n\nmodule.exports = (user_list)->\n\n #\n # A trivial Connector that simulates network delay.\n #\n class TestConnector\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)->\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n @applied_operations = []\n appliedOperationsListener = (o)=>\n @applied_operations.push o\n @execution_listener.push appliedOperationsListener\n if not (user_list?.length is 0)\n @engine.applyOps user_list[0].getHistoryBuffer()._encode()\n\n @unexecuted = {}\n\n #\n # This engine applied operations in a specific order.\n # Get the ops in the right order.\n #\n getOpsInExecutionOrder: ()->\n @applied_operations\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 for user in user_list\n if user.getUserId() isnt @HB.getUserId()\n user.getConnector().receive(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 @unexecuted[o.uid.creator] ?= []\n @unexecuted[o.uid.creator].push o\n\n #\n # Flush one operation from the line of a specific user.\n #\n flushOne: (user)->\n if @unexecuted[user]?.length > 0\n @engine.applyOp @unexecuted[user].shift()\n\n #\n # Flush one operation on a random line.\n #\n flushOneRandom: ()->\n @flushOne (_.random 0, (user_list.length-1))\n\n #\n # Flush all operations on every line.\n #\n flushAll: ()->\n for n,ops of @unexecuted\n @engine.applyOps ops\n @unexecuted = {}\n\n"],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
|
||||||
|
#
|
||||||
|
# The Engine handles how and in which order to execute operations and add operations to the HistoryBuffer.
|
||||||
|
#
|
||||||
|
class Engine
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {HistoryBuffer} HB
|
||||||
|
# @param {Array} parser Defines how to parse encoded messages.
|
||||||
|
#
|
||||||
|
constructor: (@HB, @parser)->
|
||||||
|
@unprocessed_ops = []
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parses an operatio from the json format. It uses the specified parser in your OperationType module.
|
||||||
|
#
|
||||||
|
parseOperation: (json)->
|
||||||
|
typeParser = @parser[json.type]
|
||||||
|
if typeParser?
|
||||||
|
typeParser json
|
||||||
|
else
|
||||||
|
throw new Error "You forgot to specify a parser for type #{json.type}. The message is #{JSON.stringify json}."
|
||||||
|
|
||||||
|
#
|
||||||
|
# Apply a set of operations. E.g. the operations you received from another users HB.toJson().
|
||||||
|
# @note You must not use this method when you already have ops in your HB!
|
||||||
|
#
|
||||||
|
applyOpsBundle: (ops_json)->
|
||||||
|
ops = []
|
||||||
|
for o in ops_json
|
||||||
|
ops.push @parseOperation o
|
||||||
|
for o in ops
|
||||||
|
@HB.addOperation o
|
||||||
|
for o in ops
|
||||||
|
if not o.execute()
|
||||||
|
@unprocessed_ops.push o
|
||||||
|
@tryUnprocessed()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Same as applyOps but operations that are already in the HB are not applied.
|
||||||
|
# @see Engine.applyOps
|
||||||
|
#
|
||||||
|
applyOpsCheckDouble: (ops_json)->
|
||||||
|
for o in ops_json
|
||||||
|
if @HB.getOperation(o.uid)?
|
||||||
|
@applyOp o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Apply a set of operations. (Helper for using applyOp on Arrays)
|
||||||
|
# @see Engine.applyOp
|
||||||
|
applyOps: (ops_json)->
|
||||||
|
for o in ops_json
|
||||||
|
@applyOp o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Apply an operation that you received from another peer.
|
||||||
|
#
|
||||||
|
applyOp: (op_json)->
|
||||||
|
# $parse_and_execute will return false if $o_json was parsed and executed, otherwise the parsed operadion
|
||||||
|
o = @parseOperation op_json
|
||||||
|
@HB.addToCounter o
|
||||||
|
# @HB.addOperation o
|
||||||
|
if not o.execute()
|
||||||
|
@unprocessed_ops.push o
|
||||||
|
else
|
||||||
|
@HB.addOperation o
|
||||||
|
@tryUnprocessed()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Call this method when you applied a new operation.
|
||||||
|
# It checks if operations that were previously not executable are now executable.
|
||||||
|
#
|
||||||
|
tryUnprocessed: ()->
|
||||||
|
while true
|
||||||
|
old_length = @unprocessed_ops.length
|
||||||
|
unprocessed = []
|
||||||
|
for op in @unprocessed_ops
|
||||||
|
if not op.execute()
|
||||||
|
unprocessed.push op
|
||||||
|
else
|
||||||
|
@HB.addOperation op
|
||||||
|
@unprocessed_ops = unprocessed
|
||||||
|
if @unprocessed_ops.length is old_length
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = Engine
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var t;t=function(){function t(t,e){this.HB=t,this.parser=e,this.unprocessed_ops=[]}return t.prototype.parseOperation=function(t){var e;if(e=this.parser[t.type],null!=e)return e(t);throw new Error("You forgot to specify a parser for type "+t.type+". The message is "+JSON.stringify(t)+".")},t.prototype.applyOpsBundle=function(t){var e,r,p,s,o,n,i,u;for(r=[],p=0,n=t.length;n>p;p++)e=t[p],r.push(this.parseOperation(e));for(s=0,i=r.length;i>s;s++)e=r[s],this.HB.addOperation(e);for(o=0,u=r.length;u>o;o++)e=r[o],e.execute()||this.unprocessed_ops.push(e);return this.tryUnprocessed()},t.prototype.applyOpsCheckDouble=function(t){var e,r,p,s;for(s=[],r=0,p=t.length;p>r;r++)e=t[r],s.push(null!=this.HB.getOperation(e.uid)?this.applyOp(e):void 0);return s},t.prototype.applyOps=function(t){var e,r,p,s;for(s=[],r=0,p=t.length;p>r;r++)e=t[r],s.push(this.applyOp(e));return s},t.prototype.applyOp=function(t){var e;return e=this.parseOperation(t),this.HB.addToCounter(e),e.execute()?this.HB.addOperation(e):this.unprocessed_ops.push(e),this.tryUnprocessed()},t.prototype.tryUnprocessed=function(){var t,e,r,p,s,o,n;for(n=[];;){for(t=this.unprocessed_ops.length,r=[],o=this.unprocessed_ops,p=0,s=o.length;s>p;p++)e=o[p],e.execute()?this.HB.addOperation(e):r.push(e);if(this.unprocessed_ops=r,this.unprocessed_ops.length===t)break;n.push(void 0)}return n},t}(),module.exports=t}).call(this);
|
||||||
|
//# sourceMappingURL=Engine.js.map
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
json_types_uninitialized = require "../Types/JsonTypes"
|
||||||
|
HistoryBuffer = require "../HistoryBuffer"
|
||||||
|
Engine = require "../Engine"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Framework for Json data-structures.
|
||||||
|
# Known values that are supported:
|
||||||
|
# * String
|
||||||
|
# * Integer
|
||||||
|
# * Array
|
||||||
|
#
|
||||||
|
class JsonYatta
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {String} user_id Unique id of the peer.
|
||||||
|
# @param {Connector} Connector the connector class.
|
||||||
|
#
|
||||||
|
constructor: (user_id, Connector)->
|
||||||
|
@HB = new HistoryBuffer user_id
|
||||||
|
json_types = json_types_uninitialized @HB
|
||||||
|
@engine = new Engine @HB, json_types.parser
|
||||||
|
@connector = new Connector @engine, @HB, json_types.execution_listener, @
|
||||||
|
|
||||||
|
first_word = new json_types.types.JsonType @HB.getReservedUniqueIdentifier()
|
||||||
|
@HB.addOperation(first_word).execute()
|
||||||
|
@root_element = first_word
|
||||||
|
|
||||||
|
#
|
||||||
|
# @result JsonType
|
||||||
|
#
|
||||||
|
getRootElement: ()->
|
||||||
|
@root_element
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see Engine
|
||||||
|
#
|
||||||
|
getEngine: ()->
|
||||||
|
@engine
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get the initialized connector.
|
||||||
|
#
|
||||||
|
getConnector: ()->
|
||||||
|
@connector
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see HistoryBuffer
|
||||||
|
#
|
||||||
|
getHistoryBuffer: ()->
|
||||||
|
@HB
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see JsonType.setMutableDefault
|
||||||
|
#
|
||||||
|
setMutableDefault: (mutable)->
|
||||||
|
@root_element.setMutableDefault(mutable)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get the UserId from the HistoryBuffer object.
|
||||||
|
# In most cases this will be the same as the user_id value with which
|
||||||
|
# JsonYatta was initialized (Depending on the HistoryBuffer implementation).
|
||||||
|
#
|
||||||
|
getUserId: ()->
|
||||||
|
@HB.getUserId()
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see JsonType.val
|
||||||
|
#
|
||||||
|
val : (name, content, mutable)->
|
||||||
|
@root_element.val(name, content, mutable)
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see JsonType.value
|
||||||
|
#
|
||||||
|
Object.defineProperty JsonYatta.prototype, 'value',
|
||||||
|
get : -> @root_element.value
|
||||||
|
set : (o)->
|
||||||
|
if o.constructor is {}.constructor
|
||||||
|
for o_name,o_obj of o
|
||||||
|
@val(o_name, o_obj, 'immutable')
|
||||||
|
else
|
||||||
|
throw new Error "You must only set Object values!"
|
||||||
|
window?.JsonYatta = JsonYatta
|
||||||
|
module.exports = JsonYatta
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Frameworks/JsonYatta.coffee","names":[],"mappings":"","sources":["Frameworks/JsonYatta.coffee"],"sourcesContent":["\njson_types_uninitialized = require \"../Types/JsonTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Json data-structures.\n# Known values that are supported:\n# * String\n# * Integer\n# * Array\n#\nclass JsonYatta\n\n #\n # @param {String} user_id Unique id of the peer.\n # @param {Connector} Connector the connector class.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n json_types = json_types_uninitialized @HB\n @engine = new Engine @HB, json_types.parser\n @connector = new Connector @engine, @HB, json_types.execution_listener, @\n\n first_word = new json_types.types.JsonType @HB.getReservedUniqueIdentifier()\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result JsonType\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # @see JsonType.setMutableDefault\n #\n setMutableDefault: (mutable)->\n @root_element.setMutableDefault(mutable)\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val : (name, content, mutable)->\n @root_element.val(name, content, mutable)\n\n #\n # @see JsonType.value\n #\n Object.defineProperty JsonYatta.prototype, 'value',\n get : -> @root_element.value\n set : (o)->\n if o.constructor is {}.constructor\n for o_name,o_obj of o\n @val(o_name, o_obj, 'immutable')\n else\n throw new Error \"You must only set Object values!\"\nwindow?.JsonYatta = JsonYatta\nmodule.exports = JsonYatta\n"],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var t,e,n,o;o=require("../Types/JsonTypes"),e=require("../HistoryBuffer"),t=require("../Engine"),n=function(){function n(n,r){var i,u;this.HB=new e(n),u=o(this.HB),this.engine=new t(this.HB,u.parser),this.connector=new r(this.engine,this.HB,u.execution_listener,this),i=new u.types.JsonType(this.HB.getReservedUniqueIdentifier()),this.HB.addOperation(i).execute(),this.root_element=i}return n.prototype.getRootElement=function(){return this.root_element},n.prototype.getEngine=function(){return this.engine},n.prototype.getConnector=function(){return this.connector},n.prototype.getHistoryBuffer=function(){return this.HB},n.prototype.setMutableDefault=function(t){return this.root_element.setMutableDefault(t)},n.prototype.getUserId=function(){return this.HB.getUserId()},n.prototype.val=function(t,e,n){return this.root_element.val(t,e,n)},Object.defineProperty(n.prototype,"value",{get:function(){return this.root_element.value},set:function(t){var e,n,o;if(t.constructor==={}.constructor){o=[];for(e in t)n=t[e],o.push(this.val(e,n,"immutable"));return o}throw new Error("You must only set Object values!")}}),n}(),"undefined"!=typeof window&&null!==window&&(window.JsonYatta=n),module.exports=n}).call(this);
|
||||||
|
//# sourceMappingURL=../Frameworks/JsonYatta.js.map
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Frameworks/JsonYatta.js","sources":["Frameworks/JsonYatta.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,GAAA,EAAA,EAAA,CAAA,GAA2B,QAAQ,sBACnC,EAAgB,QAAQ,oBACxB,EAAS,QAAQ,aASX,EAAA,WAMS,QAAA,GAAC,EAAS,GACrB,GAAA,GAAA,CAAA,MAAC,GAAS,GAAA,GAAc,GACxB,EAAa,EAAyB,KAAC,IACvC,KAAC,OAAa,GAAA,GAAO,KAAC,GAAI,EAAW,QACrC,KAAC,UAAgB,GAAA,GAAU,KAAC,OAAQ,KAAC,GAAI,EAAW,mBAAoB,MAExE,EAAiB,GAAA,GAAW,MAAM,SAAS,KAAC,GAAG,+BAC/C,KAAC,GAAG,aAAa,GAAY,UAC7B,KAAC,aAAe,QARlB,GAAA,UAaA,eAAgB,iBACd,MAAC,cAdH,EAAA,UAmBA,UAAW,iBACT,MAAC,QApBH,EAAA,UAyBA,aAAc,iBACZ,MAAC,WA1BH,EAAA,UA+BA,iBAAkB,iBAChB,MAAC,IAhCH,EAAA,UAqCA,kBAAmB,SAAC,SAClB,MAAC,aAAa,kBAAkB,IAtClC,EAAA,UA6CA,UAAW,iBACT,MAAC,GAAG,aA9CN,EAAA,UAmDA,IAAM,SAAC,EAAM,EAAS,SACpB,MAAC,aAAa,IAAI,EAAM,EAAS,IAKnC,OAAO,eAAe,EAAU,UAAW,SACzC,IAAM,iBAAG,MAAC,aAAa,OACvB,IAAM,SAAC,GACL,GAAA,GAAA,EAAA,CAAA,IAAG,EAAE,iBAAkB,YAAvB,CACE,SAAA,IAAA,UACE,EAAA,KAAA,KAAC,IAAI,EAAQ,EAAO,uBAEtB,KAAU,IAAA,OAAM,wFACxB,OAAQ,UAAY,GACpB,OAAO,QAAU","sourcesContent":["\njson_types_uninitialized = require \"../Types/JsonTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Json data-structures.\n# Known values that are supported:\n# * String\n# * Integer\n# * Array\n#\nclass JsonYatta\n\n #\n # @param {String} user_id Unique id of the peer.\n # @param {Connector} Connector the connector class.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n json_types = json_types_uninitialized @HB\n @engine = new Engine @HB, json_types.parser\n @connector = new Connector @engine, @HB, json_types.execution_listener, @\n\n first_word = new json_types.types.JsonType @HB.getReservedUniqueIdentifier()\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result JsonType\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # @see JsonType.setMutableDefault\n #\n setMutableDefault: (mutable)->\n @root_element.setMutableDefault(mutable)\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val : (name, content, mutable)->\n @root_element.val(name, content, mutable)\n\n #\n # @see JsonType.value\n #\n Object.defineProperty JsonYatta.prototype, 'value',\n get : -> @root_element.value\n set : (o)->\n if o.constructor is {}.constructor\n for o_name,o_obj of o\n @val(o_name, o_obj, 'immutable')\n else\n throw new Error \"You must only set Object values!\"\nwindow?.JsonYatta = JsonYatta\nmodule.exports = JsonYatta\n"],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
text_types_uninitialized = require "../Types/TextTypes"
|
||||||
|
HistoryBuffer = require "../HistoryBuffer"
|
||||||
|
Engine = require "../Engine"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Framework for Text Datastructures.
|
||||||
|
#
|
||||||
|
class TextYatta
|
||||||
|
|
||||||
|
#
|
||||||
|
# @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
|
||||||
|
@engine = new Engine @HB, text_types.parser
|
||||||
|
@connector = new Connector @engine, @HB, text_types.execution_listener
|
||||||
|
|
||||||
|
first_word = new text_types.types.Word undefined
|
||||||
|
@HB.addOperation(first_word).execute()
|
||||||
|
@root_element = first_word
|
||||||
|
|
||||||
|
#
|
||||||
|
# @result Word
|
||||||
|
#
|
||||||
|
getRootElement: ()->
|
||||||
|
@root_element
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see Engine
|
||||||
|
#
|
||||||
|
getEngine: ()->
|
||||||
|
@engine
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# JsonYatta was initialized (Depending on the HistoryBuffer implementation).
|
||||||
|
#
|
||||||
|
getUserId: ()->
|
||||||
|
@HB.getUserId()
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see JsonType.val
|
||||||
|
#
|
||||||
|
val: ()->
|
||||||
|
@root_element.val()
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see Word.insertText
|
||||||
|
#
|
||||||
|
insertText: (pos, content)->
|
||||||
|
@root_element.insertText pos, content
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see Word.deleteText
|
||||||
|
#
|
||||||
|
deleteText: (pos, length)->
|
||||||
|
@root_element.deleteText pos, length
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see Word.replaceText
|
||||||
|
#
|
||||||
|
replaceText: (text)->
|
||||||
|
@root_element.replaceText text
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = TextYatta
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Frameworks/TextYatta.coffee","names":[],"mappings":"","sources":["Frameworks/TextYatta.coffee"],"sourcesContent":["\ntext_types_uninitialized = require \"../Types/TextTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Text Datastructures.\n#\nclass TextYatta\n\n #\n # @param {String} user_id Uniqe user id that defines this peer.\n # @param {Connector} Connector The connector defines how you connect to the other peers.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n text_types = text_types_uninitialized @HB\n @engine = new Engine @HB, text_types.parser\n @connector = new Connector @engine, @HB, text_types.execution_listener\n\n first_word = new text_types.types.Word undefined\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result Word\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val: ()->\n @root_element.val()\n\n #\n # @see Word.insertText\n #\n insertText: (pos, content)->\n @root_element.insertText pos, content\n\n #\n # @see Word.deleteText\n #\n deleteText: (pos, length)->\n @root_element.deleteText pos, length\n\n #\n # @see Word.replaceText\n #\n replaceText: (text)->\n @root_element.replaceText text\n\n\nmodule.exports = TextYatta\n"],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var e,t,n,r;r=require("../Types/TextTypes"),t=require("../HistoryBuffer"),e=require("../Engine"),n=function(){function n(n,o){var i,s;this.HB=new t(n),s=r(this.HB),this.engine=new e(this.HB,s.parser),this.connector=new o(this.engine,this.HB,s.execution_listener),i=new s.types.Word(void 0),this.HB.addOperation(i).execute(),this.root_element=i}return n.prototype.getRootElement=function(){return this.root_element},n.prototype.getEngine=function(){return this.engine},n.prototype.getConnector=function(){return this.connector},n.prototype.getHistoryBuffer=function(){return this.HB},n.prototype.getUserId=function(){return this.HB.getUserId()},n.prototype.val=function(){return this.root_element.val()},n.prototype.insertText=function(e,t){return this.root_element.insertText(e,t)},n.prototype.deleteText=function(e,t){return this.root_element.deleteText(e,t)},n.prototype.replaceText=function(e){return this.root_element.replaceText(e)},n}(),module.exports=n}).call(this);
|
||||||
|
//# sourceMappingURL=../Frameworks/TextYatta.js.map
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Frameworks/TextYatta.js","sources":["Frameworks/TextYatta.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,GAAA,EAAA,EAAA,CAAA,GAA2B,QAAQ,sBACnC,EAAgB,QAAQ,oBACxB,EAAS,QAAQ,aAKX,EAAA,WAMS,QAAA,GAAC,EAAS,GACrB,GAAA,GAAA,CAAA,MAAC,GAAS,GAAA,GAAc,GACxB,EAAa,EAAyB,KAAC,IACvC,KAAC,OAAa,GAAA,GAAO,KAAC,GAAI,EAAW,QACrC,KAAC,UAAgB,GAAA,GAAU,KAAC,OAAQ,KAAC,GAAI,EAAW,oBAEpD,EAAiB,GAAA,GAAW,MAAM,KAAK,QACvC,KAAC,GAAG,aAAa,GAAY,UAC7B,KAAC,aAAe,QARlB,GAAA,UAaA,eAAgB,iBACd,MAAC,cAdH,EAAA,UAmBA,UAAW,iBACT,MAAC,QApBH,EAAA,UAyBA,aAAc,iBACZ,MAAC,WA1BH,EAAA,UA+BA,iBAAkB,iBAChB,MAAC,IAhCH,EAAA,UAuCA,UAAW,iBACT,MAAC,GAAG,aAxCN,EAAA,UA6CA,IAAK,iBACH,MAAC,aAAa,OA9ChB,EAAA,UAmDA,WAAY,SAAC,EAAK,SAChB,MAAC,aAAa,WAAW,EAAK,IApDhC,EAAA,UAyDA,WAAY,SAAC,EAAK,SAChB,MAAC,aAAa,WAAW,EAAK,IA1DhC,EAAA,UA+DA,YAAa,SAAC,SACZ,MAAC,aAAa,YAAY,SAG9B,OAAO,QAAU","sourcesContent":["\ntext_types_uninitialized = require \"../Types/TextTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Text Datastructures.\n#\nclass TextYatta\n\n #\n # @param {String} user_id Uniqe user id that defines this peer.\n # @param {Connector} Connector The connector defines how you connect to the other peers.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n text_types = text_types_uninitialized @HB\n @engine = new Engine @HB, text_types.parser\n @connector = new Connector @engine, @HB, text_types.execution_listener\n\n first_word = new text_types.types.Word undefined\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result Word\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val: ()->\n @root_element.val()\n\n #\n # @see Word.insertText\n #\n insertText: (pos, content)->\n @root_element.insertText pos, content\n\n #\n # @see Word.deleteText\n #\n deleteText: (pos, length)->\n @root_element.deleteText pos, length\n\n #\n # @see Word.replaceText\n #\n replaceText: (text)->\n @root_element.replaceText text\n\n\nmodule.exports = TextYatta\n"],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
|
||||||
|
#
|
||||||
|
# An object that holds all applied operations.
|
||||||
|
#
|
||||||
|
# @note The HistoryBuffer is commonly abbreviated to HB.
|
||||||
|
#
|
||||||
|
class HistoryBuffer
|
||||||
|
|
||||||
|
#
|
||||||
|
# Creates an empty HB.
|
||||||
|
# @param {Object} user_id Creator of the HB.
|
||||||
|
#
|
||||||
|
constructor: (@user_id)->
|
||||||
|
@operation_counter = {}
|
||||||
|
@buffer = {}
|
||||||
|
@change_listeners = []
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get the user id with wich the History Buffer was initialized.
|
||||||
|
#
|
||||||
|
getUserId: ()->
|
||||||
|
@user_id
|
||||||
|
|
||||||
|
#
|
||||||
|
# There is only one reserved unique identifier (uid), so use it wisely.
|
||||||
|
# I propose to use it in your Framework, to create something like a root element.
|
||||||
|
# An operation with this identifier is not propagated to other clients.
|
||||||
|
# This is why everybode must create the same operation with this uid.
|
||||||
|
#
|
||||||
|
getReservedUniqueIdentifier: ()->
|
||||||
|
{
|
||||||
|
creator : '_'
|
||||||
|
op_number : '_'
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get the operation counter that describes the current state of the document.
|
||||||
|
#
|
||||||
|
getOperationCounter: ()->
|
||||||
|
res = {}
|
||||||
|
for user,ctn of @operation_counter
|
||||||
|
res[user] = ctn
|
||||||
|
res
|
||||||
|
|
||||||
|
#
|
||||||
|
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||||
|
#
|
||||||
|
_encode: (state_vector={})->
|
||||||
|
json = []
|
||||||
|
unknown = (user, o_number)->
|
||||||
|
if (not user?) or (not o_number?)
|
||||||
|
throw new Error "dah!"
|
||||||
|
not state_vector[user]? or state_vector[user] <= o_number
|
||||||
|
|
||||||
|
for u_name,user of @buffer
|
||||||
|
for o_number,o of user
|
||||||
|
if not isNaN(parseInt(o_number)) and unknown(u_name, o_number)
|
||||||
|
o_json = o._encode()
|
||||||
|
if o.next_cl?
|
||||||
|
o_next = o.next_cl
|
||||||
|
while o_next.next_cl? and unknown(o_next.creator, o_next.op_number)
|
||||||
|
o_next = o_next.next_cl
|
||||||
|
o_json.next = o_next.getUid()
|
||||||
|
else if o.prev_cl?
|
||||||
|
o_prev = o.prev_cl
|
||||||
|
while o_prev.prev_cl? and unknown(o_next.creator, o_next.op_number)
|
||||||
|
o_prev = o_prev.prev_cl
|
||||||
|
o_json.prev = o_prev.getUid()
|
||||||
|
json.push o_json
|
||||||
|
|
||||||
|
json
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get the number of operations that were created by a user.
|
||||||
|
# Accordingly you will get the next operation number that is expected from that user.
|
||||||
|
# This will increment the operation counter.
|
||||||
|
#
|
||||||
|
getNextOperationIdentifier: (user_id)->
|
||||||
|
if not user_id?
|
||||||
|
user_id = @user_id
|
||||||
|
if not @operation_counter[user_id]?
|
||||||
|
@operation_counter[user_id] = 0
|
||||||
|
uid =
|
||||||
|
'creator' : user_id
|
||||||
|
'op_number' : @operation_counter[user_id]
|
||||||
|
@operation_counter[user_id]++
|
||||||
|
uid
|
||||||
|
|
||||||
|
#
|
||||||
|
# Retrieve an operation from a unique id.
|
||||||
|
#
|
||||||
|
getOperation: (uid)->
|
||||||
|
if uid instanceof Object
|
||||||
|
@buffer[uid.creator]?[uid.op_number]
|
||||||
|
else if not uid?
|
||||||
|
else
|
||||||
|
throw new Error "This type of uid is not defined!"
|
||||||
|
#
|
||||||
|
# Add an operation to the HB. Note that this will not link it against
|
||||||
|
# other operations (it wont executed)
|
||||||
|
#
|
||||||
|
addOperation: (o)->
|
||||||
|
if not @buffer[o.creator]?
|
||||||
|
@buffer[o.creator] = {}
|
||||||
|
if @buffer[o.creator][o.op_number]?
|
||||||
|
throw new Error "You must not overwrite operations!"
|
||||||
|
@buffer[o.creator][o.op_number] = o
|
||||||
|
o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Increment the operation_counter that defines the current state of the Engine.
|
||||||
|
#
|
||||||
|
addToCounter: (o)->
|
||||||
|
if not @operation_counter[o.creator]?
|
||||||
|
@operation_counter[o.creator] = 0
|
||||||
|
if typeof o.op_number is 'number' and o.creator isnt @getUserId()
|
||||||
|
@operation_counter[o.creator]++
|
||||||
|
#if @operation_counter[o.creator] isnt (o.op_number + 1)
|
||||||
|
#console.log (@operation_counter[o.creator] - (o.op_number + 1))
|
||||||
|
#console.log o
|
||||||
|
#throw new Error "You don't receive operations in the proper order. Try counting like this 0,1,2,3,4,.. ;)"
|
||||||
|
|
||||||
|
module.exports = HistoryBuffer
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var r;r=function(){function r(r){this.user_id=r,this.operation_counter={},this.buffer={},this.change_listeners=[]}return r.prototype.getUserId=function(){return this.user_id},r.prototype.getReservedUniqueIdentifier=function(){return{creator:"_",op_number:"_"}},r.prototype.getOperationCounter=function(){var r,t,e,o;t={},o=this.operation_counter;for(e in o)r=o[e],t[e]=r;return t},r.prototype._encode=function(r){var t,e,o,n,i,u,c,p,f,l;null==r&&(r={}),t=[],p=function(t,e){if(null==t||null==e)throw new Error("dah!");return null==r[t]||r[t]<=e},l=this.buffer;for(c in l){f=l[c];for(i in f)if(e=f[i],!isNaN(parseInt(i))&&p(c,i)){if(o=e._encode(),null!=e.next_cl){for(n=e.next_cl;null!=n.next_cl&&p(n.creator,n.op_number);)n=n.next_cl;o.next=n.getUid()}else if(null!=e.prev_cl){for(u=e.prev_cl;null!=u.prev_cl&&p(n.creator,n.op_number);)u=u.prev_cl;o.prev=u.getUid()}t.push(o)}}return t},r.prototype.getNextOperationIdentifier=function(r){var t;return null==r&&(r=this.user_id),null==this.operation_counter[r]&&(this.operation_counter[r]=0),t={creator:r,op_number:this.operation_counter[r]},this.operation_counter[r]++,t},r.prototype.getOperation=function(r){var t;if(r instanceof Object)return null!=(t=this.buffer[r.creator])?t[r.op_number]:void 0;if(null!=r)throw new Error("This type of uid is not defined!")},r.prototype.addOperation=function(r){if(null==this.buffer[r.creator]&&(this.buffer[r.creator]={}),null!=this.buffer[r.creator][r.op_number])throw new Error("You must not overwrite operations!");return this.buffer[r.creator][r.op_number]=r,r},r.prototype.addToCounter=function(r){return null==this.operation_counter[r.creator]&&(this.operation_counter[r.creator]=0),"number"==typeof r.op_number&&r.creator!==this.getUserId()?this.operation_counter[r.creator]++:void 0},r}(),module.exports=r}).call(this);
|
||||||
|
//# sourceMappingURL=HistoryBuffer.js.map
|
||||||
Executable
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,439 @@
|
|||||||
|
module.exports = (HB)->
|
||||||
|
# @see Engine.parse
|
||||||
|
parser = {}
|
||||||
|
execution_listener = []
|
||||||
|
|
||||||
|
#
|
||||||
|
# A generic interface to operations.
|
||||||
|
#
|
||||||
|
# An operation has the following methods:
|
||||||
|
# _encode: encodes an operation (needed only if instance of this operation is sent).
|
||||||
|
# execute: execute the effects of this operations. Good examples are Insert-type and AddName-type
|
||||||
|
# val: in the case that the operation holds a value
|
||||||
|
#
|
||||||
|
# Furthermore an encodable operation has a parser.
|
||||||
|
#
|
||||||
|
class Operation
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
# @see HistoryBuffer.getNextOperationIdentifier
|
||||||
|
#
|
||||||
|
constructor: (uid)->
|
||||||
|
if not uid?
|
||||||
|
uid = HB.getNextOperationIdentifier()
|
||||||
|
{
|
||||||
|
'creator': @creator
|
||||||
|
'op_number' : @op_number
|
||||||
|
} = uid
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add an event listener. It depends on the operation which events are supported.
|
||||||
|
# @param {String} event Name of the event.
|
||||||
|
# @param {Function} f f is executed in case the event fires.
|
||||||
|
#
|
||||||
|
on: (event, f)->
|
||||||
|
@event_listeners ?= {}
|
||||||
|
@event_listeners[event] ?= []
|
||||||
|
@event_listeners[event].push f
|
||||||
|
|
||||||
|
#
|
||||||
|
# Fire an event.
|
||||||
|
# TODO: Do something with timeouts. You don't want this to fire for every operation (e.g. insert).
|
||||||
|
#
|
||||||
|
callEvent: (event, args)->
|
||||||
|
if @event_listeners[event]?
|
||||||
|
for f in @event_listeners[event]
|
||||||
|
f.call @, event, args
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set the parent of this operation.
|
||||||
|
#
|
||||||
|
setParent: (o)->
|
||||||
|
@parent = o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Computes a unique identifier (uid) that identifies this operation.
|
||||||
|
#
|
||||||
|
getUid: ()->
|
||||||
|
{ 'creator': @creator, 'op_number': @op_number }
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
# Notify the all the listeners.
|
||||||
|
#
|
||||||
|
execute: ()->
|
||||||
|
@is_executed = true
|
||||||
|
for l in execution_listener
|
||||||
|
l @_encode()
|
||||||
|
@
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
# Operations may depend on other operations (linked lists, etc.).
|
||||||
|
# The saveOperation and validateSavedOperations methods provide
|
||||||
|
# an easy way to refer to these operations via an uid or object reference.
|
||||||
|
#
|
||||||
|
# For example: We can create a new Delete operation that deletes the operation $o like this
|
||||||
|
# - var d = new Delete(uid, $o); or
|
||||||
|
# - var d = new Delete(uid, $o.getUid());
|
||||||
|
# Either way we want to access $o via d.deletes. In the second case validateSavedOperations must be called first.
|
||||||
|
#
|
||||||
|
# @overload saveOperation(name, op_uid)
|
||||||
|
# @param {String} name The name of the operation. After validating (with validateSavedOperations) the instantiated operation will be accessible via this[name].
|
||||||
|
# @param {Object} op_uid A uid that refers to an operation
|
||||||
|
# @overload saveOperation(name, op)
|
||||||
|
# @param {String} name The name of the operation. After calling this function op is accessible via this[name].
|
||||||
|
# @param {Operation} op An Operation object
|
||||||
|
#
|
||||||
|
saveOperation: (name, op)->
|
||||||
|
|
||||||
|
#
|
||||||
|
# Every instance of $Operation must have an $execute function.
|
||||||
|
# We use duck-typing to check if op is instantiated since there
|
||||||
|
# could exist multiple classes of $Operation
|
||||||
|
#
|
||||||
|
if op?.execute?
|
||||||
|
# is instantiated
|
||||||
|
@[name] = op
|
||||||
|
else if op?
|
||||||
|
# not initialized. Do it when calling $validateSavedOperations()
|
||||||
|
@unchecked ?= {}
|
||||||
|
@unchecked[name] = op
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
# After calling this function all not instantiated operations will be accessible.
|
||||||
|
# @see Operation.saveOperation
|
||||||
|
#
|
||||||
|
# @return [Boolean] Whether it was possible to instantiate all operations.
|
||||||
|
#
|
||||||
|
validateSavedOperations: ()->
|
||||||
|
uninstantiated = {}
|
||||||
|
success = @
|
||||||
|
for name, op_uid of @unchecked
|
||||||
|
op = HB.getOperation op_uid
|
||||||
|
if op
|
||||||
|
@[name] = op
|
||||||
|
else
|
||||||
|
uninstantiated[name] = op_uid
|
||||||
|
success = false
|
||||||
|
delete @unchecked
|
||||||
|
if not success
|
||||||
|
@unchecked = uninstantiated
|
||||||
|
success
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# A simple Delete-type operation that deletes an Insert-type operation.
|
||||||
|
#
|
||||||
|
class Delete extends Operation
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
# @param {Object} deletes UID or reference of the operation that this to be deleted.
|
||||||
|
#
|
||||||
|
constructor: (uid, deletes)->
|
||||||
|
@saveOperation 'deletes', deletes
|
||||||
|
super uid
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
# Convert all relevant information of this operation to the json-format.
|
||||||
|
# This result can be sent to other clients.
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
{
|
||||||
|
'type': "Delete"
|
||||||
|
'uid': @getUid()
|
||||||
|
'deletes': @deletes.getUid()
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
# Apply the deletion.
|
||||||
|
#
|
||||||
|
execute: ()->
|
||||||
|
if @validateSavedOperations()
|
||||||
|
@deletes.applyDelete @
|
||||||
|
super
|
||||||
|
@
|
||||||
|
else
|
||||||
|
false
|
||||||
|
|
||||||
|
#
|
||||||
|
# Define how to parse Delete operations.
|
||||||
|
#
|
||||||
|
parser['Delete'] = (o)->
|
||||||
|
{
|
||||||
|
'uid' : uid
|
||||||
|
'deletes': deletes_uid
|
||||||
|
} = o
|
||||||
|
new Delete uid, deletes_uid
|
||||||
|
|
||||||
|
#
|
||||||
|
# A simple insert-type operation.
|
||||||
|
#
|
||||||
|
# An insert operation is always positioned between two other insert operations.
|
||||||
|
# Internally this is realized as associative lists, whereby each insert operation has a predecessor and a successor.
|
||||||
|
# For the sake of efficiency we maintain two lists:
|
||||||
|
# - The short-list (abbrev. sl) maintains only the operations that are not deleted
|
||||||
|
# - The complete-list (abbrev. cl) maintains all operations
|
||||||
|
#
|
||||||
|
class Insert extends Operation
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
# @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)
|
||||||
|
#
|
||||||
|
# @see HistoryBuffer.getNextOperationIdentifier
|
||||||
|
#
|
||||||
|
constructor: (uid, prev_cl, next_cl, origin)->
|
||||||
|
@saveOperation 'prev_cl', prev_cl
|
||||||
|
@saveOperation 'next_cl', next_cl
|
||||||
|
if origin?
|
||||||
|
@saveOperation 'origin', origin
|
||||||
|
else
|
||||||
|
@saveOperation 'origin', prev_cl
|
||||||
|
super uid
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
#
|
||||||
|
applyDelete: (o)->
|
||||||
|
@deleted_by ?= []
|
||||||
|
@deleted_by.push o
|
||||||
|
|
||||||
|
#
|
||||||
|
# If isDeleted() is true this operation won't be maintained in the sl
|
||||||
|
#
|
||||||
|
isDeleted: ()->
|
||||||
|
@deleted_by?.length > 0
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
# The amount of positions that $this operation was moved to the right.
|
||||||
|
#
|
||||||
|
getDistanceToOrigin: ()->
|
||||||
|
d = 0
|
||||||
|
o = @prev_cl
|
||||||
|
while true
|
||||||
|
if @origin is o
|
||||||
|
break
|
||||||
|
d++
|
||||||
|
#TODO: delete this
|
||||||
|
if @ is @prev_cl
|
||||||
|
throw new Error "this should not happen ;) "
|
||||||
|
o = o.prev_cl
|
||||||
|
d
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
# Update the short list
|
||||||
|
# TODO (Unused)
|
||||||
|
update_sl: ()->
|
||||||
|
o = @prev_cl
|
||||||
|
update: (dest_cl,dest_sl)->
|
||||||
|
while true
|
||||||
|
if o.isDeleted()
|
||||||
|
o = o[dest_cl]
|
||||||
|
else
|
||||||
|
@[dest_sl] = o
|
||||||
|
|
||||||
|
break
|
||||||
|
update "prev_cl", "prev_sl"
|
||||||
|
update "next_cl", "prev_sl"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
# Include this operation in the associative lists.
|
||||||
|
#
|
||||||
|
execute: ()->
|
||||||
|
if @is_executed?
|
||||||
|
return @
|
||||||
|
if not @validateSavedOperations()
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
if @prev_cl?.validateSavedOperations() and @next_cl?.validateSavedOperations() and @prev_cl.next_cl isnt @
|
||||||
|
distance_to_origin = 0
|
||||||
|
o = @prev_cl.next_cl
|
||||||
|
i = 0
|
||||||
|
# $this has to find a unique position between origin and the next known character
|
||||||
|
# case 1: $origin equals $o.origin: the $creator parameter decides if left or right
|
||||||
|
# let $OL= [o1,o2,o3,o4], whereby $this is to be inserted between o1 and o4
|
||||||
|
# o2,o3 and o4 origin is 1 (the position of o2)
|
||||||
|
# there is the case that $this.creator < o2.creator, but o3.creator < $this.creator
|
||||||
|
# then o2 knows o3. Since on another client $OL could be [o1,o3,o4] the problem is complex
|
||||||
|
# therefore $this would be always to the right of o3
|
||||||
|
# case 2: $origin < $o.origin
|
||||||
|
# if current $this insert_position > $o origin: $this ins
|
||||||
|
# else $insert_position will not change (maybe we encounter case 1 later, then this will be to the right of $o)
|
||||||
|
# case 3: $origin > $o.origin
|
||||||
|
# $this insert_position is to the left of $o (forever!)
|
||||||
|
while true
|
||||||
|
if not o?
|
||||||
|
# TODO: Debugging
|
||||||
|
console.log JSON.stringify @prev_cl.getUid()
|
||||||
|
console.log JSON.stringify @next_cl.getUid()
|
||||||
|
if o isnt @next_cl
|
||||||
|
# $o happened concurrently
|
||||||
|
if o.getDistanceToOrigin() is i
|
||||||
|
# case 1
|
||||||
|
if o.creator < @creator
|
||||||
|
@prev_cl = o
|
||||||
|
distance_to_origin = i + 1
|
||||||
|
else
|
||||||
|
# nop
|
||||||
|
else if o.getDistanceToOrigin() < i
|
||||||
|
# case 2
|
||||||
|
if i - distance_to_origin <= o.getDistanceToOrigin()
|
||||||
|
@prev_cl = o
|
||||||
|
distance_to_origin = i + 1
|
||||||
|
else
|
||||||
|
#nop
|
||||||
|
else
|
||||||
|
# case 3
|
||||||
|
break
|
||||||
|
i++
|
||||||
|
o = o.next_cl
|
||||||
|
else
|
||||||
|
# $this knows that $o exists,
|
||||||
|
break
|
||||||
|
# now reconnect everything
|
||||||
|
@next_cl = @prev_cl.next_cl
|
||||||
|
@prev_cl.next_cl = @
|
||||||
|
@next_cl.prev_cl = @
|
||||||
|
super # notify the execution_listeners
|
||||||
|
@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Defines an object that is cannot be changed. You can use this to set an immutable string, or a number.
|
||||||
|
#
|
||||||
|
class ImmutableObject extends Insert
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
# @param {Object} content
|
||||||
|
#
|
||||||
|
constructor: (uid, @content, prev, next, origin)->
|
||||||
|
super uid, prev, next, origin
|
||||||
|
|
||||||
|
#
|
||||||
|
# @return [String] The content of this operation.
|
||||||
|
#
|
||||||
|
val : ()->
|
||||||
|
@content
|
||||||
|
|
||||||
|
#
|
||||||
|
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
json = {
|
||||||
|
'type': "ImmutableObject"
|
||||||
|
'uid' : @getUid()
|
||||||
|
'content' : @content
|
||||||
|
}
|
||||||
|
if @prev_cl?
|
||||||
|
json['prev'] = @prev_cl.getUid()
|
||||||
|
if @next_cl?
|
||||||
|
json['next'] = @next_cl.getUid()
|
||||||
|
if @origin? and @origin isnt @prev_cl
|
||||||
|
json["origin"] = @origin.getUid()
|
||||||
|
json
|
||||||
|
|
||||||
|
parser['ImmutableObject'] = (json)->
|
||||||
|
{
|
||||||
|
'uid' : uid
|
||||||
|
'content' : content
|
||||||
|
'prev': prev
|
||||||
|
'next': next
|
||||||
|
'origin' : origin
|
||||||
|
} = json
|
||||||
|
new ImmutableObject uid, content, prev, next, origin
|
||||||
|
|
||||||
|
#
|
||||||
|
# A delimiter is placed at the end and at the beginning of the associative lists.
|
||||||
|
# This is necessary in order to have a beginning and an end even if the content
|
||||||
|
# of the Engine is empty.
|
||||||
|
#
|
||||||
|
class Delimiter extends Operation
|
||||||
|
#
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
# @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)
|
||||||
|
#
|
||||||
|
# @see HistoryBuffer.getNextOperationIdentifier
|
||||||
|
#
|
||||||
|
constructor: (uid, prev_cl, next_cl, origin)->
|
||||||
|
@saveOperation 'prev_cl', prev_cl
|
||||||
|
@saveOperation 'next_cl', next_cl
|
||||||
|
@saveOperation 'origin', prev_cl
|
||||||
|
super uid
|
||||||
|
|
||||||
|
#
|
||||||
|
# If isDeleted() is true this operation won't be maintained in the sl
|
||||||
|
#
|
||||||
|
isDeleted: ()->
|
||||||
|
false
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
#
|
||||||
|
execute: ()->
|
||||||
|
if @unchecked?['next_cl']?
|
||||||
|
super
|
||||||
|
else if @unchecked?['prev_cl']
|
||||||
|
if @validateSavedOperations()
|
||||||
|
if @prev_cl.next_cl?
|
||||||
|
throw new Error "Probably duplicated operations"
|
||||||
|
@prev_cl.next_cl = @
|
||||||
|
delete @prev_cl.unchecked.next_cl
|
||||||
|
super
|
||||||
|
else
|
||||||
|
false
|
||||||
|
else if @prev_cl? and not @prev_cl.next_cl?
|
||||||
|
delete @prev_cl.unchecked.next_cl
|
||||||
|
@prev_cl.next_cl = @
|
||||||
|
else if @prev_cl? or @next_cl?
|
||||||
|
super
|
||||||
|
else
|
||||||
|
throw new Error "Delimiter is unsufficient defined!"
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
{
|
||||||
|
'type' : "Delimiter"
|
||||||
|
'uid' : @getUid()
|
||||||
|
'prev' : @prev_cl?.getUid()
|
||||||
|
'next' : @next_cl?.getUid()
|
||||||
|
}
|
||||||
|
|
||||||
|
parser['Delimiter'] = (json)->
|
||||||
|
{
|
||||||
|
'uid' : uid
|
||||||
|
'prev' : prev
|
||||||
|
'next' : next
|
||||||
|
} = json
|
||||||
|
new Delimiter uid, prev, next
|
||||||
|
|
||||||
|
# This is what this module exports after initializing it with the HistoryBuffer
|
||||||
|
{
|
||||||
|
'types' :
|
||||||
|
'Delete' : Delete
|
||||||
|
'Insert' : Insert
|
||||||
|
'Delimiter': Delimiter
|
||||||
|
'Operation': Operation
|
||||||
|
'ImmutableObject' : ImmutableObject
|
||||||
|
'parser' : parser
|
||||||
|
'execution_listener' : execution_listener
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Executable
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,210 @@
|
|||||||
|
text_types_uninitialized = require "./TextTypes"
|
||||||
|
|
||||||
|
module.exports = (HB)->
|
||||||
|
text_types = text_types_uninitialized HB
|
||||||
|
types = text_types.types
|
||||||
|
parser = text_types.parser
|
||||||
|
|
||||||
|
createJsonWrapper = (_jsonType)->
|
||||||
|
|
||||||
|
#
|
||||||
|
# A JsonWrapper was intended to be a convenient wrapper for the JsonType.
|
||||||
|
# But it can make things more difficult than they are.
|
||||||
|
# @see JsonType
|
||||||
|
#
|
||||||
|
# @example create a JsonWrapper
|
||||||
|
# # You get a JsonWrapper from a JsonType by calling
|
||||||
|
# w = yatta.value
|
||||||
|
#
|
||||||
|
# It creates Javascripts -getter and -setter methods for each property that JsonType maintains.
|
||||||
|
# @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
|
||||||
|
#
|
||||||
|
# @example Getter Example
|
||||||
|
# # you can access the x property of yatta by calling
|
||||||
|
# w.x
|
||||||
|
# # instead of
|
||||||
|
# yatta.val('x')
|
||||||
|
#
|
||||||
|
# @note You can only overwrite existing values! Setting a new property won't have any effect!
|
||||||
|
#
|
||||||
|
# @example Setter Example
|
||||||
|
# # you can set an existing x property of yatta by calling
|
||||||
|
# w.x = "text"
|
||||||
|
# # instead of
|
||||||
|
# yatta.val('x', "text")
|
||||||
|
#
|
||||||
|
# In order to set a new property you have to overwrite an existing property.
|
||||||
|
# Therefore the JsonWrapper supports a special feature that should make things more convenient
|
||||||
|
# (we can argue about that, use the JsonType if you don't like it ;).
|
||||||
|
# If you overwrite an object property of the JsonWrapper with a new object, it will result in a merged version of the objects.
|
||||||
|
# Let w.p the property that is to be overwritten and o the new value. E.g. w.p = o
|
||||||
|
# * The result has all properties of o
|
||||||
|
# * The result has all properties of w.p if they don't occur under the same property-name in o.
|
||||||
|
#
|
||||||
|
# @example Conflict Example
|
||||||
|
# yatta.value = {a : "string"}
|
||||||
|
# w = yatta.value
|
||||||
|
# console.log(w) # {a : "string"}
|
||||||
|
# w.a = {a : {b : "string"}}
|
||||||
|
# console.log(w) # {a : {b : "String"}}
|
||||||
|
# w.a = {a : {c : 4}}
|
||||||
|
# console.log(w) # {a : {b : "String", c : 4}}
|
||||||
|
#
|
||||||
|
# @example Common Pitfalls
|
||||||
|
# w = yatta.value
|
||||||
|
# # Setting a new property
|
||||||
|
# w.newProperty = "Awesome"
|
||||||
|
# console.log(w.newProperty == "Awesome") # false, w.newProperty is undefined
|
||||||
|
# # overwrite the w object
|
||||||
|
# w = {newProperty : "Awesome"}
|
||||||
|
# console.log(w.newProperty == "Awesome") # true!, but ..
|
||||||
|
# console.log(yatta.value.newProperty == "Awesome") # false, you are only allowed to set properties!
|
||||||
|
# # The solution
|
||||||
|
# yatta.value = {newProperty : "Awesome"}
|
||||||
|
# console.log(w.newProperty == "Awesome") # true!
|
||||||
|
#
|
||||||
|
class JsonWrapper
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {JsonType} jsonType Instance of the JsonType that this class wrappes.
|
||||||
|
#
|
||||||
|
constructor: (jsonType)->
|
||||||
|
for name, obj of jsonType.map
|
||||||
|
do (name, obj)->
|
||||||
|
Object.defineProperty JsonWrapper.prototype, name,
|
||||||
|
get : ->
|
||||||
|
x = obj.val()
|
||||||
|
if x instanceof JsonType
|
||||||
|
createJsonWrapper x
|
||||||
|
else if x instanceof types.ImmutableObject
|
||||||
|
x.val()
|
||||||
|
else
|
||||||
|
x
|
||||||
|
set : (o)->
|
||||||
|
if o.constructor is {}.constructor
|
||||||
|
overwrite = jsonType.val(name)
|
||||||
|
for o_name,o_obj of o
|
||||||
|
overwrite.val(o_name, o_obj, 'immutable')
|
||||||
|
else
|
||||||
|
jsonType.val(name, o, 'immutable')
|
||||||
|
enumerable: true
|
||||||
|
configurable: false
|
||||||
|
new JsonWrapper _jsonType
|
||||||
|
|
||||||
|
#
|
||||||
|
# Manages Object-like values.
|
||||||
|
#
|
||||||
|
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
|
||||||
|
|
||||||
|
#
|
||||||
|
# Whether the default is 'mutable' (true) or 'immutable' (false)
|
||||||
|
#
|
||||||
|
mutable_default:
|
||||||
|
true
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set if the default is 'mutable' or 'immutable'
|
||||||
|
# @param {String|Boolean} mutable Set either 'mutable' / true or 'immutable' / false
|
||||||
|
setMutableDefault: (mutable)->
|
||||||
|
if mutable is true or mutable is 'mutable'
|
||||||
|
JsonType.prototype.mutable_default = true
|
||||||
|
else if mutable is false or mutable is 'immutable'
|
||||||
|
JsonType.prototype.mutable_default = false
|
||||||
|
else
|
||||||
|
throw new Error 'Set mutable either "mutable" or "immutable"!'
|
||||||
|
'OK'
|
||||||
|
|
||||||
|
#
|
||||||
|
# @overload val()
|
||||||
|
# Get this as a Json object.
|
||||||
|
# @return [Json]
|
||||||
|
#
|
||||||
|
# @overload val(name)
|
||||||
|
# Get value of a property.
|
||||||
|
# @param {String} name Name of the object property.
|
||||||
|
# @return [JsonType|Word|String|Object] Depending on the value of the property. If mutable it will return a Operation-type object, if immutable it will return String/Object.
|
||||||
|
#
|
||||||
|
# @overload val(name, content)
|
||||||
|
# Set a new property.
|
||||||
|
# @param {String} name Name of the object property.
|
||||||
|
# @param {Object|String} content Content of the object property.
|
||||||
|
# @return [JsonType] This object. (supports chaining)
|
||||||
|
#
|
||||||
|
val: (name, content, mutable)->
|
||||||
|
if typeof name is 'object'
|
||||||
|
# Special case. First argument is an object. Then the second arg is mutable.
|
||||||
|
# Keep that in mind when reading the following..
|
||||||
|
for o_name,o of name
|
||||||
|
@val(o_name,o,content)
|
||||||
|
@
|
||||||
|
else if name? and content?
|
||||||
|
if mutable?
|
||||||
|
if mutable is true or mutable is 'mutable'
|
||||||
|
mutable = true
|
||||||
|
else
|
||||||
|
mutable = false
|
||||||
|
else
|
||||||
|
mutable = @mutable_default
|
||||||
|
if typeof content is 'function'
|
||||||
|
@ # Just do nothing
|
||||||
|
else if ((not mutable) or typeof content is 'number') and content.constructor isnt Object
|
||||||
|
obj = HB.addOperation(new types.ImmutableObject undefined, content).execute()
|
||||||
|
super name, obj
|
||||||
|
else
|
||||||
|
if typeof content is 'string'
|
||||||
|
word = HB.addOperation(new types.Word undefined).execute()
|
||||||
|
word.insertText 0, content
|
||||||
|
super name, word
|
||||||
|
else if content.constructor is Object
|
||||||
|
json = HB.addOperation(new JsonType undefined, content, mutable).execute()
|
||||||
|
super name, json
|
||||||
|
else
|
||||||
|
throw new Error "You must not set #{typeof content}-types in collaborative Json-objects!"
|
||||||
|
else
|
||||||
|
super name, content
|
||||||
|
|
||||||
|
Object.defineProperty JsonType.prototype, 'value',
|
||||||
|
get : -> createJsonWrapper @
|
||||||
|
set : (o)->
|
||||||
|
if o.constructor is {}.constructor
|
||||||
|
for o_name,o_obj of o
|
||||||
|
@val(o_name, o_obj, 'immutable')
|
||||||
|
else
|
||||||
|
throw new Error "You must only set Object values!"
|
||||||
|
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
{
|
||||||
|
'type' : "JsonType"
|
||||||
|
'uid' : @getUid()
|
||||||
|
}
|
||||||
|
|
||||||
|
parser['JsonType'] = (json)->
|
||||||
|
{
|
||||||
|
'uid' : uid
|
||||||
|
} = json
|
||||||
|
new JsonType uid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
types['JsonType'] = JsonType
|
||||||
|
|
||||||
|
text_types
|
||||||
|
|
||||||
|
|
||||||
Executable
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var t,e={}.hasOwnProperty,r=function(t,r){function n(){this.constructor=t}for(var o in r)e.call(r,o)&&(t[o]=r[o]);return n.prototype=r.prototype,t.prototype=new n,t.__super__=r.prototype,t};t=require("./TextTypes"),module.exports=function(e){var n,o,u,i,a;return i=t(e),a=i.types,u=i.parser,o=function(t){var e;return new(e=function(){function t(e){var r,u,i,l;l=e.map,i=function(r,u){return Object.defineProperty(t.prototype,r,{get:function(){var t;return t=u.val(),t instanceof n?o(t):t instanceof a.ImmutableObject?t.val():t},set:function(t){var n,o,u,i;if(t.constructor==={}.constructor){u=e.val(r),i=[];for(n in t)o=t[n],i.push(u.val(n,o,"immutable"));return i}return e.val(r,t,"immutable")},enumerable:!0,configurable:!1})};for(r in l)u=l[r],i(r,u)}return t}())(t)},n=function(t){function n(t,e,r){var o,u;if(n.__super__.constructor.call(this,t),null!=e){if("object"!=typeof e)throw new Error("The initial value of JsonTypes must be of type Object! (current type: "+typeof e+")");for(o in e)u=e[o],this.val(o,u,r)}}return r(n,t),n.prototype.mutable_default=!0,n.prototype.setMutableDefault=function(t){if(t===!0||"mutable"===t)n.prototype.mutable_default=!0;else{if(t!==!1&&"immutable"!==t)throw new Error('Set mutable either "mutable" or "immutable"!');n.prototype.mutable_default=!1}return"OK"},n.prototype.val=function(t,r,o){var u,i,l,c,p;if("object"==typeof t){for(l in t)i=t[l],this.val(l,i,r);return this}if(null!=t&&null!=r){if(o=null!=o?o===!0||"mutable"===o?!0:!1:this.mutable_default,"function"==typeof r)return this;if(o&&"number"!=typeof r||r.constructor===Object){if("string"==typeof r)return p=e.addOperation(new a.Word(void 0)).execute(),p.insertText(0,r),n.__super__.val.call(this,t,p);if(r.constructor===Object)return u=e.addOperation(new n(void 0,r,o)).execute(),n.__super__.val.call(this,t,u);throw new Error("You must not set "+typeof r+"-types in collaborative Json-objects!")}return c=e.addOperation(new a.ImmutableObject(void 0,r)).execute(),n.__super__.val.call(this,t,c)}return n.__super__.val.call(this,t,r)},Object.defineProperty(n.prototype,"value",{get:function(){return o(this)},set:function(t){var e,r,n;if(t.constructor==={}.constructor){n=[];for(e in t)r=t[e],n.push(this.val(e,r,"immutable"));return n}throw new Error("You must only set Object values!")}}),n.prototype._encode=function(){return{type:"JsonType",uid:this.getUid()}},n}(a.MapManager),u.JsonType=function(t){var e;return e=t.uid,new n(e)},a.JsonType=n,i}}).call(this);
|
||||||
|
//# sourceMappingURL=../Types/JsonTypes.js.map
|
||||||
Executable
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,310 @@
|
|||||||
|
basic_types_uninitialized = require "./BasicTypes"
|
||||||
|
|
||||||
|
module.exports = (HB)->
|
||||||
|
basic_types = basic_types_uninitialized HB
|
||||||
|
types = basic_types.types
|
||||||
|
parser = basic_types.parser
|
||||||
|
|
||||||
|
#
|
||||||
|
# Manages map like objects. E.g. Json-Type and XML attributes.
|
||||||
|
#
|
||||||
|
class MapManager extends types.Operation
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
#
|
||||||
|
constructor: (uid)->
|
||||||
|
@map = {}
|
||||||
|
super uid
|
||||||
|
|
||||||
|
#
|
||||||
|
# @see JsonTypes.val
|
||||||
|
#
|
||||||
|
val: (name, content)->
|
||||||
|
if content?
|
||||||
|
if not @map[name]?
|
||||||
|
HB.addOperation(new AddName undefined, @, name).execute()
|
||||||
|
@map[name].replace content
|
||||||
|
@
|
||||||
|
else if name?
|
||||||
|
obj = @map[name]?.val()
|
||||||
|
if obj instanceof types.ImmutableObject
|
||||||
|
obj.val()
|
||||||
|
else
|
||||||
|
obj
|
||||||
|
else
|
||||||
|
result = {}
|
||||||
|
for name,o of @map
|
||||||
|
obj = o.val()
|
||||||
|
if obj instanceof types.ImmutableObject or obj instanceof MapManager
|
||||||
|
obj = obj.val()
|
||||||
|
result[name] = obj
|
||||||
|
result
|
||||||
|
|
||||||
|
#
|
||||||
|
# When a new property in a map manager is created, then the uids of the inserted Operations
|
||||||
|
# must be unique (think about concurrent operations). Therefore only an AddName operation is allowed to
|
||||||
|
# add a property in a MapManager. If two AddName operations on the same MapManager name happen concurrently
|
||||||
|
# only one will AddName operation will be executed.
|
||||||
|
#
|
||||||
|
class AddName extends types.Operation
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
# @param {Object} map_manager Uid or reference to the MapManager.
|
||||||
|
# @param {String} name Name of the property that will be added.
|
||||||
|
#
|
||||||
|
constructor: (uid, map_manager, @name)->
|
||||||
|
@saveOperation 'map_manager', map_manager
|
||||||
|
super uid
|
||||||
|
|
||||||
|
#
|
||||||
|
# If map_manager doesn't have the property name, then add it.
|
||||||
|
# The ReplaceManager that is being written on the property is unique
|
||||||
|
# in such a way that if AddName is executed (from another peer) it will
|
||||||
|
# always have the same result (ReplaceManager, and its beginning and end are the same)
|
||||||
|
#
|
||||||
|
execute: ()->
|
||||||
|
if not @validateSavedOperations()
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
uid_r = @map_manager.getUid()
|
||||||
|
uid_r.op_number = "_#{uid_r.op_number}_RM_#{@name}"
|
||||||
|
if not HB.getOperation(uid_r)?
|
||||||
|
uid_beg = @map_manager.getUid()
|
||||||
|
uid_beg.op_number = "_#{uid_beg.op_number}_RM_#{@name}_beginning"
|
||||||
|
uid_end = @map_manager.getUid()
|
||||||
|
uid_end.op_number = "_#{uid_end.op_number}_RM_#{@name}_end"
|
||||||
|
beg = HB.addOperation(new types.Delimiter uid_beg, undefined, uid_end).execute()
|
||||||
|
end = HB.addOperation(new types.Delimiter uid_end, beg, undefined).execute()
|
||||||
|
#beg.execute()
|
||||||
|
@map_manager.map[@name] = HB.addOperation(new ReplaceManager undefined, uid_r, beg, end).execute()
|
||||||
|
super
|
||||||
|
|
||||||
|
#
|
||||||
|
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
{
|
||||||
|
'type' : "AddName"
|
||||||
|
'uid' : @getUid()
|
||||||
|
'map_manager' : @map_manager.getUid()
|
||||||
|
'name' : @name
|
||||||
|
}
|
||||||
|
|
||||||
|
parser['AddName'] = (json)->
|
||||||
|
{
|
||||||
|
'map_manager' : map_manager
|
||||||
|
'uid' : uid
|
||||||
|
'name' : name
|
||||||
|
} = json
|
||||||
|
new AddName uid, map_manager, name
|
||||||
|
|
||||||
|
#
|
||||||
|
# Manages a list of Insert-type operations.
|
||||||
|
#
|
||||||
|
class ListManager extends types.Insert
|
||||||
|
|
||||||
|
#
|
||||||
|
# A ListManager maintains a non-empty list that has a beginning and an end (both Delimiters!)
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
# @param {Delimiter} beginning Reference or Object.
|
||||||
|
# @param {Delimiter} end Reference or Object.
|
||||||
|
constructor: (uid, beginning, end, prev, next, origin)->
|
||||||
|
if beginning? and end?
|
||||||
|
@saveOperation 'beginning', beginning
|
||||||
|
@saveOperation 'end', end
|
||||||
|
else
|
||||||
|
@beginning = HB.addOperation new types.Delimiter undefined, undefined, undefined
|
||||||
|
@end = HB.addOperation new types.Delimiter undefined, @beginning, undefined
|
||||||
|
@beginning.next_cl = @end
|
||||||
|
@beginning.execute()
|
||||||
|
@end.execute()
|
||||||
|
super uid, prev, next, origin
|
||||||
|
|
||||||
|
|
||||||
|
# Get the element previous to the delemiter at the end
|
||||||
|
getLastOperation: ()->
|
||||||
|
@end.prev_cl
|
||||||
|
|
||||||
|
# similar to the above
|
||||||
|
getFirstOperation: ()->
|
||||||
|
@beginning.next_cl
|
||||||
|
|
||||||
|
# Transforms the the list to an array
|
||||||
|
# Doesn't return left-right delimiter.
|
||||||
|
toArray: ()->
|
||||||
|
o = @beginning.next_cl
|
||||||
|
result = []
|
||||||
|
while o isnt @end
|
||||||
|
result.push o
|
||||||
|
o = o.next_cl
|
||||||
|
result
|
||||||
|
|
||||||
|
#
|
||||||
|
# Retrieves the x-th not deleted element.
|
||||||
|
#
|
||||||
|
getOperationByPosition: (position)->
|
||||||
|
o = @beginning.next_cl
|
||||||
|
if position > 0
|
||||||
|
while true
|
||||||
|
o = o.next_cl
|
||||||
|
if not o.isDeleted()
|
||||||
|
position -= 1
|
||||||
|
if position is 0
|
||||||
|
break
|
||||||
|
if o instanceof types.Delimiter
|
||||||
|
throw new Error "position parameter exceeded the length of the document!"
|
||||||
|
o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Adds support for replace. The ReplaceManager manages Replaceable operations.
|
||||||
|
# Each Replaceable holds a value that is now replaceable.
|
||||||
|
#
|
||||||
|
# The Word-type has implemented support for replace
|
||||||
|
# @see Word
|
||||||
|
#
|
||||||
|
class ReplaceManager extends ListManager
|
||||||
|
#
|
||||||
|
# @param {Operation} initial_content Initialize this with a Replaceable that holds the initial_content.
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
# @param {Delimiter} beginning Reference or Object.
|
||||||
|
# @param {Delimiter} end Reference or Object.
|
||||||
|
constructor: (initial_content, uid, beginning, end, prev, next, origin)->
|
||||||
|
super uid, beginning, end, prev, next, origin
|
||||||
|
if initial_content?
|
||||||
|
@replace initial_content
|
||||||
|
|
||||||
|
#
|
||||||
|
# Replace the existing word with a new word.
|
||||||
|
#
|
||||||
|
replace: (content)->
|
||||||
|
o = @getLastOperation()
|
||||||
|
op = new Replaceable content, @, undefined, o, o.next_cl
|
||||||
|
HB.addOperation(op).execute()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get the value of this Word
|
||||||
|
# @return {String}
|
||||||
|
#
|
||||||
|
val: ()->
|
||||||
|
o = @getLastOperation()
|
||||||
|
if o instanceof types.Delimiter
|
||||||
|
throw new Error "dtrn"
|
||||||
|
o.val()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
json =
|
||||||
|
{
|
||||||
|
'type': "ReplaceManager"
|
||||||
|
'uid' : @getUid()
|
||||||
|
'beginning' : @beginning.getUid()
|
||||||
|
'end' : @end.getUid()
|
||||||
|
}
|
||||||
|
if @prev_cl? and @next_cl?
|
||||||
|
json['prev'] = @prev_cl.getUid()
|
||||||
|
json['next'] = @next_cl.getUid()
|
||||||
|
if @origin? and @origin isnt @prev_cl
|
||||||
|
json["origin"] = @origin.getUid()
|
||||||
|
json
|
||||||
|
|
||||||
|
parser["ReplaceManager"] = (json)->
|
||||||
|
{
|
||||||
|
'content' : content
|
||||||
|
'uid' : uid
|
||||||
|
'prev': prev
|
||||||
|
'next': next
|
||||||
|
'origin' : origin
|
||||||
|
'beginning' : beginning
|
||||||
|
'end' : end
|
||||||
|
} = json
|
||||||
|
new ReplaceManager content, uid, beginning, end, prev, next, origin
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The ReplaceManager manages Replaceables.
|
||||||
|
# @see ReplaceManager
|
||||||
|
#
|
||||||
|
class Replaceable extends types.Insert
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {Operation} content The value that this Replaceable holds.
|
||||||
|
# @param {ReplaceManager} parent Used to replace this Replaceable with another one.
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
#
|
||||||
|
constructor: (content, parent, uid, prev, next, origin)->
|
||||||
|
@saveOperation 'content', content
|
||||||
|
@saveOperation 'parent', parent
|
||||||
|
if not (prev? and next? and content?)
|
||||||
|
throw new Error "You must define content, prev, and next for Replaceable-types!"
|
||||||
|
super uid, prev, next, origin
|
||||||
|
|
||||||
|
#
|
||||||
|
# Return the content that this operation holds.
|
||||||
|
#
|
||||||
|
val: ()->
|
||||||
|
@content
|
||||||
|
|
||||||
|
#
|
||||||
|
# Replace the content of this replaceable with new content.
|
||||||
|
#
|
||||||
|
replace: (content)->
|
||||||
|
@parent.replace content
|
||||||
|
|
||||||
|
#
|
||||||
|
# If possible set the replace manager in the content.
|
||||||
|
# @see Word.setReplaceManager
|
||||||
|
#
|
||||||
|
execute: ()->
|
||||||
|
if not @validateSavedOperations()
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
@content.setReplaceManager?(@parent)
|
||||||
|
super
|
||||||
|
@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
json =
|
||||||
|
{
|
||||||
|
'type': "Replaceable"
|
||||||
|
'content': @content.getUid()
|
||||||
|
'ReplaceManager' : @parent.getUid()
|
||||||
|
'prev': @prev_cl.getUid()
|
||||||
|
'next': @next_cl.getUid()
|
||||||
|
'uid' : @getUid()
|
||||||
|
}
|
||||||
|
if @origin? and @origin isnt @prev_cl
|
||||||
|
json["origin"] = @origin.getUid()
|
||||||
|
json
|
||||||
|
|
||||||
|
parser["Replaceable"] = (json)->
|
||||||
|
{
|
||||||
|
'content' : content
|
||||||
|
'ReplaceManager' : parent
|
||||||
|
'uid' : uid
|
||||||
|
'prev': prev
|
||||||
|
'next': next
|
||||||
|
'origin' : origin
|
||||||
|
} = json
|
||||||
|
new Replaceable content, parent, uid, prev, next, origin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
types['ListManager'] = ListManager
|
||||||
|
types['MapManager'] = MapManager
|
||||||
|
types['ReplaceManager'] = ReplaceManager
|
||||||
|
types['Replaceable'] = Replaceable
|
||||||
|
|
||||||
|
basic_types
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var e,t={}.hasOwnProperty,n=function(e,n){function i(){this.constructor=e}for(var r in n)t.call(n,r)&&(e[r]=n[r]);return i.prototype=n.prototype,e.prototype=new i,e.__super__=n.prototype,e};e=require("./BasicTypes"),module.exports=function(t){var i,r,a,o,p,s,u,c;return s=e(t),c=s.types,u=s.parser,a=function(e){function r(e){this.map={},r.__super__.constructor.call(this,e)}return n(r,e),r.prototype.val=function(e,n){var a,o,p,s,u;if(null!=n)return null==this.map[e]&&t.addOperation(new i(void 0,this,e)).execute(),this.map[e].replace(n),this;if(null!=e)return o=null!=(s=this.map[e])?s.val():void 0,o instanceof c.ImmutableObject?o.val():o;p={},u=this.map;for(e in u)a=u[e],o=a.val(),(o instanceof c.ImmutableObject||o instanceof r)&&(o=o.val()),p[e]=o;return p},r}(c.Operation),i=function(e){function i(e,t,n){this.name=n,this.saveOperation("map_manager",t),i.__super__.constructor.call(this,e)}return n(i,e),i.prototype.execute=function(){var e,n,r,a,p;return this.validateSavedOperations()?(p=this.map_manager.getUid(),p.op_number="_"+p.op_number+"_RM_"+this.name,null==t.getOperation(p)&&(r=this.map_manager.getUid(),r.op_number="_"+r.op_number+"_RM_"+this.name+"_beginning",a=this.map_manager.getUid(),a.op_number="_"+a.op_number+"_RM_"+this.name+"_end",e=t.addOperation(new c.Delimiter(r,void 0,a)).execute(),n=t.addOperation(new c.Delimiter(a,e,void 0)).execute(),this.map_manager.map[this.name]=t.addOperation(new o(void 0,p,e,n)).execute()),i.__super__.execute.apply(this,arguments)):!1},i.prototype._encode=function(){return{type:"AddName",uid:this.getUid(),map_manager:this.map_manager.getUid(),name:this.name}},i}(c.Operation),u.AddName=function(e){var t,n,r;return t=e.map_manager,r=e.uid,n=e.name,new i(r,t,n)},r=function(e){function i(e,n,r,a,o,p){null!=n&&null!=r?(this.saveOperation("beginning",n),this.saveOperation("end",r)):(this.beginning=t.addOperation(new c.Delimiter(void 0,void 0,void 0)),this.end=t.addOperation(new c.Delimiter(void 0,this.beginning,void 0)),this.beginning.next_cl=this.end,this.beginning.execute(),this.end.execute()),i.__super__.constructor.call(this,e,a,o,p)}return n(i,e),i.prototype.getLastOperation=function(){return this.end.prev_cl},i.prototype.getFirstOperation=function(){return this.beginning.next_cl},i.prototype.toArray=function(){var e,t;for(e=this.beginning.next_cl,t=[];e!==this.end;)t.push(e),e=e.next_cl;return t},i.prototype.getOperationByPosition=function(e){var t;if(t=this.beginning.next_cl,e>0)for(;;){if(t=t.next_cl,t.isDeleted()||(e-=1),0===e)break;if(t instanceof c.Delimiter)throw new Error("position parameter exceeded the length of the document!")}return t},i}(c.Insert),o=function(e){function i(e,t,n,r,a,o,p){i.__super__.constructor.call(this,t,n,r,a,o,p),null!=e&&this.replace(e)}return n(i,e),i.prototype.replace=function(e){var n,i;return n=this.getLastOperation(),i=new p(e,this,void 0,n,n.next_cl),t.addOperation(i).execute()},i.prototype.val=function(){var e;if(e=this.getLastOperation(),e instanceof c.Delimiter)throw new Error("dtrn");return e.val()},i.prototype._encode=function(){var e;return e={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(e.prev=this.prev_cl.getUid(),e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},i}(r),u.ReplaceManager=function(e){var t,n,i,r,a,p,s;return n=e.content,s=e.uid,p=e.prev,r=e.next,a=e.origin,t=e.beginning,i=e.end,new o(n,s,t,i,p,r,a)},p=function(e){function t(e,n,i,r,a,o){if(this.saveOperation("content",e),this.saveOperation("parent",n),null==r||null==a||null==e)throw new Error("You must define content, prev, and next for Replaceable-types!");t.__super__.constructor.call(this,i,r,a,o)}return n(t,e),t.prototype.val=function(){return this.content},t.prototype.replace=function(e){return this.parent.replace(e)},t.prototype.execute=function(){var e;return this.validateSavedOperations()?("function"==typeof(e=this.content).setReplaceManager&&e.setReplaceManager(this.parent),t.__super__.execute.apply(this,arguments),this):!1},t.prototype._encode=function(){var e;return e={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(c.Insert),u.Replaceable=function(e){var t,n,i,r,a,o;return t=e.content,r=e.ReplaceManager,o=e.uid,a=e.prev,n=e.next,i=e.origin,new p(t,r,o,a,n,i)},c.ListManager=r,c.MapManager=a,c.ReplaceManager=o,c.Replaceable=p,s}}).call(this);
|
||||||
|
//# sourceMappingURL=../Types/StructuredTypes.js.map
|
||||||
Executable
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,177 @@
|
|||||||
|
structured_types_uninitialized = require "./StructuredTypes"
|
||||||
|
|
||||||
|
module.exports = (HB)->
|
||||||
|
structured_types = structured_types_uninitialized HB
|
||||||
|
types = structured_types.types
|
||||||
|
parser = structured_types.parser
|
||||||
|
|
||||||
|
#
|
||||||
|
# At the moment TextDelete type equals the Delete type in BasicTypes.
|
||||||
|
# @see BasicTypes.Delete
|
||||||
|
#
|
||||||
|
class TextDelete extends types.Delete
|
||||||
|
parser["TextDelete"] = parser["Delete"]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Extends the basic Insert type to an operation that holds a text value
|
||||||
|
#
|
||||||
|
class TextInsert extends types.Insert
|
||||||
|
#
|
||||||
|
# @param {String} content The content of this Insert-type Operation. Usually you restrict the length of content to size 1
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
#
|
||||||
|
constructor: (@content, uid, prev, next, origin)->
|
||||||
|
if not (prev? and next?)
|
||||||
|
throw new Error "You must define prev, and next for TextInsert-types!"
|
||||||
|
super uid, prev, next, origin
|
||||||
|
#
|
||||||
|
# Retrieve the effective length of the $content of this operation.
|
||||||
|
#
|
||||||
|
getLength: ()->
|
||||||
|
if @isDeleted()
|
||||||
|
0
|
||||||
|
else
|
||||||
|
@content.length
|
||||||
|
|
||||||
|
#
|
||||||
|
# The result will be concatenated with the results from the other insert operations
|
||||||
|
# in order to retrieve the content of the engine.
|
||||||
|
# @see HistoryBuffer.toExecutedArray
|
||||||
|
#
|
||||||
|
val: (current_position)->
|
||||||
|
if @isDeleted()
|
||||||
|
""
|
||||||
|
else
|
||||||
|
@content
|
||||||
|
|
||||||
|
#
|
||||||
|
# Convert all relevant information of this operation to the json-format.
|
||||||
|
# This result can be send to other clients.
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
json =
|
||||||
|
{
|
||||||
|
'type': "TextInsert"
|
||||||
|
'content': @content
|
||||||
|
'uid' : @getUid()
|
||||||
|
'prev': @prev_cl.getUid()
|
||||||
|
'next': @next_cl.getUid()
|
||||||
|
}
|
||||||
|
if @origin? and @origin isnt @prev_cl
|
||||||
|
json["origin"] = @origin.getUid()
|
||||||
|
json
|
||||||
|
|
||||||
|
parser["TextInsert"] = (json)->
|
||||||
|
{
|
||||||
|
'content' : content
|
||||||
|
'uid' : uid
|
||||||
|
'prev': prev
|
||||||
|
'next': next
|
||||||
|
'origin' : origin
|
||||||
|
} = json
|
||||||
|
new TextInsert content, uid, prev, next, origin
|
||||||
|
|
||||||
|
#
|
||||||
|
# Handles a Text-like data structures with support for insertText/deleteText at a word-position.
|
||||||
|
#
|
||||||
|
class Word extends types.ListManager
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
|
||||||
|
#
|
||||||
|
constructor: (uid, beginning, end, prev, next, origin)->
|
||||||
|
super uid, beginning, end, prev, next, origin
|
||||||
|
|
||||||
|
#
|
||||||
|
# Inserts a string into the word
|
||||||
|
#
|
||||||
|
insertText: (position, content)->
|
||||||
|
o = @getOperationByPosition position
|
||||||
|
for c in content
|
||||||
|
op = new TextInsert c, undefined, o.prev_cl, o
|
||||||
|
HB.addOperation(op).execute()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Deletes a part of the word.
|
||||||
|
#
|
||||||
|
deleteText: (position, length)->
|
||||||
|
o = @getOperationByPosition position
|
||||||
|
|
||||||
|
for i in [0...length]
|
||||||
|
d = HB.addOperation(new TextDelete undefined, o).execute()
|
||||||
|
o = o.next_cl
|
||||||
|
while o.isDeleted()
|
||||||
|
if o instanceof types.Delimiter
|
||||||
|
throw new Error "You can't delete more than there is.."
|
||||||
|
o = o.next_cl
|
||||||
|
d._encode()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Replace the content of this word with another one. Concurrent replacements are not merged!
|
||||||
|
# Only one of the replacements will be used.
|
||||||
|
#
|
||||||
|
# Can only be used if the ReplaceManager was set!
|
||||||
|
# @see Word.setReplaceManager
|
||||||
|
#
|
||||||
|
replaceText: (text)->
|
||||||
|
if @replace_manager?
|
||||||
|
word = HB.addOperation(new Word undefined).execute()
|
||||||
|
word.insertText 0, text
|
||||||
|
@replace_manager.replace(word)
|
||||||
|
else
|
||||||
|
throw new Error "This type is currently not maintained by a ReplaceManager!"
|
||||||
|
|
||||||
|
#
|
||||||
|
# @returns [Json] A Json object.
|
||||||
|
#
|
||||||
|
val: ()->
|
||||||
|
c = for o in @toArray()
|
||||||
|
if o.val?
|
||||||
|
o.val()
|
||||||
|
else
|
||||||
|
""
|
||||||
|
c.join('')
|
||||||
|
|
||||||
|
#
|
||||||
|
# In most cases you would embed a Word in a Replaceable, wich is handled by the ReplaceManager in order
|
||||||
|
# to provide replace functionality.
|
||||||
|
#
|
||||||
|
setReplaceManager: (op)->
|
||||||
|
@saveOperation 'replace_manager', op
|
||||||
|
@validateSavedOperations
|
||||||
|
|
||||||
|
#
|
||||||
|
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||||
|
#
|
||||||
|
_encode: ()->
|
||||||
|
json = {
|
||||||
|
'type': "Word"
|
||||||
|
'uid' : @getUid()
|
||||||
|
'beginning' : @beginning.getUid()
|
||||||
|
'end' : @end.getUid()
|
||||||
|
}
|
||||||
|
if @prev_cl?
|
||||||
|
json['prev'] = @prev_cl.getUid()
|
||||||
|
if @next_cl?
|
||||||
|
json['next'] = @next_cl.getUid()
|
||||||
|
if @origin? and @origin isnt @prev_cl
|
||||||
|
json["origin"] = @origin.getUid()
|
||||||
|
json
|
||||||
|
|
||||||
|
parser['Word'] = (json)->
|
||||||
|
{
|
||||||
|
'uid' : uid
|
||||||
|
'beginning' : beginning
|
||||||
|
'end' : end
|
||||||
|
'prev': prev
|
||||||
|
'next': next
|
||||||
|
'origin' : origin
|
||||||
|
} = json
|
||||||
|
new Word uid, beginning, end, prev, next, origin
|
||||||
|
|
||||||
|
types['TextInsert'] = TextInsert
|
||||||
|
types['TextDelete'] = TextDelete
|
||||||
|
types['Word'] = Word
|
||||||
|
structured_types
|
||||||
|
|
||||||
|
|
||||||
Executable
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){var t,e={}.hasOwnProperty,n=function(t,n){function r(){this.constructor=t}for(var i in n)e.call(n,i)&&(t[i]=n[i]);return r.prototype=n.prototype,t.prototype=new r,t.__super__=n.prototype,t};t=require("./StructuredTypes"),module.exports=function(e){var r,i,o,s,u,c;return u=t(e),c=u.types,s=u.parser,r=function(t){function e(){return e.__super__.constructor.apply(this,arguments)}return n(e,t),e}(c.Delete),s.TextDelete=s.Delete,i=function(t){function e(t,n,r,i,o){if(this.content=t,null==r||null==i)throw new Error("You must define prev, and next for TextInsert-types!");e.__super__.constructor.call(this,n,r,i,o)}return n(e,t),e.prototype.getLength=function(){return this.isDeleted()?0:this.content.length},e.prototype.val=function(){return this.isDeleted()?"":this.content},e.prototype._encode=function(){var t;return t={type:"TextInsert",content:this.content,uid:this.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},e}(c.Insert),s.TextInsert=function(t){var e,n,r,o,s;return e=t.content,s=t.uid,o=t.prev,n=t.next,r=t.origin,new i(e,s,o,n,r)},o=function(t){function o(t,e,n,r,i,s){o.__super__.constructor.call(this,t,e,n,r,i,s)}return n(o,t),o.prototype.insertText=function(t,n){var r,o,s,u,c,p;for(o=this.getOperationByPosition(t),p=[],u=0,c=n.length;c>u;u++)r=n[u],s=new i(r,void 0,o.prev_cl,o),p.push(e.addOperation(s).execute());return p},o.prototype.deleteText=function(t,n){var i,o,s,u,p;for(s=this.getOperationByPosition(t),p=[],o=u=0;n>=0?n>u:u>n;o=n>=0?++u:--u){for(i=e.addOperation(new r(void 0,s)).execute(),s=s.next_cl;s.isDeleted();){if(s instanceof c.Delimiter)throw new Error("You can't delete more than there is..");s=s.next_cl}p.push(i._encode())}return p},o.prototype.replaceText=function(t){var n;if(null!=this.replace_manager)return n=e.addOperation(new o(void 0)).execute(),n.insertText(0,t),this.replace_manager.replace(n);throw new Error("This type is currently not maintained by a ReplaceManager!")},o.prototype.val=function(){var t,e;return t=function(){var t,n,r,i;for(r=this.toArray(),i=[],t=0,n=r.length;n>t;t++)e=r[t],i.push(null!=e.val?e.val():"");return i}.call(this),t.join("")},o.prototype.setReplaceManager=function(t){return this.saveOperation("replace_manager",t),this.validateSavedOperations},o.prototype._encode=function(){var t;return t={type:"Word",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&(t.prev=this.prev_cl.getUid()),null!=this.next_cl&&(t.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},o}(c.ListManager),s.Word=function(t){var e,n,r,i,s,u;return u=t.uid,e=t.beginning,n=t.end,s=t.prev,r=t.next,i=t.origin,new o(u,e,n,s,r,i)},c.TextInsert=i,c.TextDelete=r,c.Word=o,u}}).call(this);
|
||||||
|
//# sourceMappingURL=../Types/TextTypes.js.map
|
||||||
Executable
+1
File diff suppressed because one or more lines are too long
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Types/XmlTypes.coffee","names":[],"mappings":"","sources":["Types/XmlTypes.coffee"],"sourcesContent":[""],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){}).call(this);
|
||||||
|
//# sourceMappingURL=../Types/XmlTypes.js.map
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"Types/XmlTypes.js","sources":["Types/XmlTypes.coffee"],"names":[],"mappings":"CA8KkB","sourcesContent":[""],"sourceRoot":"/source/"}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
exports['IwcConnector'] =
|
||||||
|
require './Connectors/IwcConnector'
|
||||||
|
exports['TestConnector'] =
|
||||||
|
require './Connectors/TestConnector'
|
||||||
|
exports['JsonYatta'] =
|
||||||
|
require './Frameworks/JsonYatta'
|
||||||
|
exports['TextYatta'] =
|
||||||
|
require './Frameworks/TextYatta'
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
(function(){exports.IwcConnector=require("./Connectors/IwcConnector"),exports.TestConnector=require("./Connectors/TestConnector"),exports.JsonYatta=require("./Frameworks/JsonYatta"),exports.TextYatta=require("./Frameworks/TextYatta")}).call(this);
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"index.js","sources":["index.coffee"],"names":[],"mappings":"CACA,WAAA,QAAQ,aACN,QAAQ,6BACV,QAAQ,cACN,QAAQ,8BACV,QAAQ,UACN,QAAQ,0BACV,QAAQ,UACN,QAAQ","sourcesContent":["\nexports['IwcConnector'] =\n require './Connectors/IwcConnector'\nexports['TestConnector'] =\n require './Connectors/TestConnector'\nexports['JsonYatta'] =\n require './Frameworks/JsonYatta'\nexports['TextYatta'] =\n require './Frameworks/TextYatta'\n\n"],"sourceRoot":"/source/"}
|
||||||
File diff suppressed because one or more lines are too long
@@ -2,11 +2,11 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Test Yatta!</title>
|
<title>Test Yatta!</title>
|
||||||
<link rel="stylesheet" href="../../../node_modules/mocha/mocha.css" />
|
<link rel="stylesheet" href="../../node_modules/mocha/mocha.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="mocha"></div>
|
<div id="mocha"></div>
|
||||||
<script src="../../../node_modules/mocha/mocha.js"></script>
|
<script src="../../node_modules/mocha/mocha.js"></script>
|
||||||
<script>mocha.setup('bdd')</script>
|
<script>mocha.setup('bdd')</script>
|
||||||
<script src="Yatta_test.js"></script>
|
<script src="Yatta_test.js"></script>
|
||||||
<script>
|
<script>
|
||||||
File diff suppressed because it is too large
Load Diff
-10
File diff suppressed because one or more lines are too long
@@ -1,31 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Module>
|
|
||||||
<ModulePrefs title="Video upload" description="Upload videos in Sevianno" author="Kevin Jahns, Chair of Computer Science 5, RWTH Aachen University, Germany" author_email="jahns@dbis.rwth-aachen.de" scrolling="true">
|
|
||||||
<Require feature="dynamic-height"/>
|
|
||||||
|
|
||||||
</ModulePrefs>
|
|
||||||
|
|
||||||
<Content type="html"><![CDATA[
|
|
||||||
<script src="http://open-app.googlecode.com/files/openapp.js"></script>
|
|
||||||
<script src="http://dbis.rwth-aachen.de/gadgets/lib/las/storage.js"></script>
|
|
||||||
<script src="http://dbis.rwth-aachen.de/gadgets/iwc/lib/iwc.js"></script>
|
|
||||||
<script src="http://dbis.rwth-aachen.de/gadgets/lib/las/lasAjaxClient.js"></script>
|
|
||||||
<script src="http://dbis.rwth-aachen.de/~jahns/role-widgets/widgetbundles/libraries/DUIClient.js"></script>
|
|
||||||
<script src="../dest/browser/Frameworks/JsonIwcYatta.js"></script>
|
|
||||||
<script src="../Frameworks/JsonIwcYatta.js"></script>
|
|
||||||
<script>
|
|
||||||
function init(){
|
|
||||||
window.createIwcConnector(function(Connector){
|
|
||||||
console.log("initializing..");
|
|
||||||
yatta = new window.JsonYatta(1, Connector);
|
|
||||||
var dui = yatta.getConnector().duiClient
|
|
||||||
dui.getAppState()
|
|
||||||
console.log("initialized!");
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
$(document).ready(init)
|
|
||||||
</script>
|
|
||||||
<h1> awesomewidget </h1>
|
|
||||||
]]></Content>
|
|
||||||
</Module>
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Module>
|
|
||||||
<ModulePrefs title="Video upload" description="Upload videos in Sevianno" author="Kevin Jahns, Chair of Computer Science 5, RWTH Aachen University, Germany" author_email="jahns@dbis.rwth-aachen.de" scrolling="true">
|
|
||||||
<Require feature="dynamic-height"/>
|
|
||||||
|
|
||||||
</ModulePrefs>
|
|
||||||
|
|
||||||
<Content type="html"><![CDATA[
|
|
||||||
<script type="application/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
|
|
||||||
<script src="http://open-app.googlecode.com/files/openapp.js"></script>
|
|
||||||
<script src="http://dbis.rwth-aachen.de/gadgets/lib/las/storage.js"></script>
|
|
||||||
<script src="http://dbis.rwth-aachen.de/gadgets/iwc/lib/iwc.js"></script>
|
|
||||||
<script src="http://dbis.rwth-aachen.de/gadgets/lib/las/lasAjaxClient.js"></script>
|
|
||||||
<script src="../Widgets/libs/DUIClient.js"></script>
|
|
||||||
<script src="../Frameworks/JsonIwcYatta.js"></script>
|
|
||||||
<script>
|
|
||||||
function init(){
|
|
||||||
function f(){
|
|
||||||
console.log("beginning");
|
|
||||||
window.createIwcConnector(function(Connector){
|
|
||||||
console.log("initializing..");
|
|
||||||
yatta = new window.JsonYatta(2, Connector);
|
|
||||||
console.log("initialized!");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setTimeout(f, 8000)
|
|
||||||
}
|
|
||||||
$(document).ready(init)
|
|
||||||
</script>
|
|
||||||
<h1> awesomewidget </h1>
|
|
||||||
]]></Content>
|
|
||||||
</Module>
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<Module>
|
|
||||||
<ModulePrefs
|
|
||||||
title="IWC Test Stub"
|
|
||||||
description="A widget for tracing and sending ROLE IWC intents. Recommended for developers of IWC-enabled widgets."
|
|
||||||
author="Dominik Renzel, Chair of Computer Science 5, RWTH Aachen University, Germany"
|
|
||||||
author_email="renzel@dbis.rwth-aachen.de"
|
|
||||||
height="500">
|
|
||||||
<Require feature="dynamic-height"/>
|
|
||||||
</ModulePrefs>
|
|
||||||
<Content type="html">
|
|
||||||
<![CDATA[
|
|
||||||
<style type="text/css">
|
|
||||||
* {
|
|
||||||
font-family: Verdana;
|
|
||||||
font-size: 8pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
#accordion {
|
|
||||||
overflow: auto;
|
|
||||||
height: 310px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pubform, .entry {
|
|
||||||
border: 1pt solid black
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr td.ui-state-default{
|
|
||||||
width: 20%;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr td.input, tr td.ui-widget-content {
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pub_form tr td input {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pub_form tr td textarea {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css"/>
|
|
||||||
|
|
||||||
<script type="application/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
|
|
||||||
<script type="application/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"</script>
|
|
||||||
|
|
||||||
<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/gadgets/iwc/lib/date.js"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var counter = 0;
|
|
||||||
var iwcClient = null;
|
|
||||||
|
|
||||||
function renderIntent(intent){
|
|
||||||
var result = "<table class='entry'>";
|
|
||||||
|
|
||||||
|
|
||||||
var sender = intent.sender;
|
|
||||||
var publisher = "me";
|
|
||||||
var source = sender;
|
|
||||||
|
|
||||||
if (sender.indexOf("?sender=") > -1){
|
|
||||||
var ts = sender.split("?sender=");
|
|
||||||
publisher = ts[0].split("/")[0];
|
|
||||||
source = ts[1];
|
|
||||||
} else {
|
|
||||||
publisher = "<b><i>me</i></b>";
|
|
||||||
source = sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
result += "<tr><td class='ui-state-default'>Publisher</td><td class='ui-widget-content'>" + publisher + "</td></tr>";
|
|
||||||
result += "<tr><td class='ui-state-default'>Source</td><td class='ui-widget-content'>" + source + "</td></tr>";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var comp = intent.component;
|
|
||||||
if(comp === ""){
|
|
||||||
comp = "*";
|
|
||||||
}
|
|
||||||
|
|
||||||
result += "<tr><td class='ui-state-default'>Component</td><td class='ui-widget-content,value'>" + comp + "</td></tr>";
|
|
||||||
result += "<tr><td class='ui-state-default'>Action</td><td class='ui-widget-content'>" + intent.action + "</td></tr>";
|
|
||||||
result += "<tr><td class='ui-state-default'>Data</td><td class='ui-widget-content'>" + intent.data + "</td></tr>";
|
|
||||||
result += "<tr><td class='ui-state-default'>Datatype</td><td class='ui-widget-content'>" + intent.dataType + "</td></tr>";
|
|
||||||
result += "<tr><td class='ui-state-default'>Categories</td><td class='ui-widget-content'>" + intent.categories + "</td></tr>";
|
|
||||||
result += "<tr><td class='ui-state-default'>Flags</td><td class='ui-widget-content'>" + intent.flags + "</td></tr>";
|
|
||||||
result += "<tr><td class='ui-state-default'>Extras</td><td class='ui-widget-content'> " + JSON.stringify(intent.extras) + "</td></tr>";
|
|
||||||
|
|
||||||
result += "</table>";
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function collectIntent(){
|
|
||||||
var action = $("#pub_action").val();
|
|
||||||
console.log("Action: " + action);
|
|
||||||
|
|
||||||
var sender = $("#pub_source").val();
|
|
||||||
if(!($("#pub_publisher").val() == 'me')){
|
|
||||||
sender = $("#pub_publisher").val() + "?sender=" + sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
var categories = $("#pub_categories").val().split(",");
|
|
||||||
var flags = $("#pub_flags").val().split(",");
|
|
||||||
|
|
||||||
try{
|
|
||||||
var extras = $.parseJSON($("#pub_extras").val());
|
|
||||||
} catch(error) {
|
|
||||||
alert("Corrupt JSON specified for extras");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var intent = {
|
|
||||||
"component": $("#pub_component").val(),
|
|
||||||
"sender": sender,
|
|
||||||
"data": $("#pub_data").val(),
|
|
||||||
"dataType":$("#pub_datatype").val(),
|
|
||||||
"action":$("#pub_action").val(),
|
|
||||||
"categories":categories,
|
|
||||||
"flags": flags,
|
|
||||||
"extras": extras
|
|
||||||
};
|
|
||||||
return intent;
|
|
||||||
}
|
|
||||||
|
|
||||||
function init(){
|
|
||||||
|
|
||||||
iwcClient = new iwc.Client();
|
|
||||||
|
|
||||||
var iwcCallback = function(intent) {
|
|
||||||
var date = new Date();
|
|
||||||
var format = "yyyy-MM-dd kk:mm:ss";
|
|
||||||
var dates = formatDate(date,format)+"."+date.getMilliseconds();
|
|
||||||
$('#accordion').prepend("<h3><a href='#'>#" + counter + " - " + intent.action + " (" + dates + ")</a></h3><div>" + renderIntent(intent) + "</div>").accordion('destroy').accordion();
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
iwcClient.connect(iwcCallback);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
$( "#accordion" ).accordion({
|
|
||||||
collapsible: true
|
|
||||||
});
|
|
||||||
|
|
||||||
$( "#clearb" ).button().click(function() {
|
|
||||||
counter = 0;
|
|
||||||
$( "#accordion" ).accordion('destroy').empty().accordion();
|
|
||||||
});
|
|
||||||
|
|
||||||
$( "#sendb" ).button().click(function() {
|
|
||||||
$("#sendintent").dialog('open');
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#exint").dialog({
|
|
||||||
autoOpen: false,
|
|
||||||
heigth: 340,
|
|
||||||
width: 350,
|
|
||||||
modal: true
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#sendintent").dialog({
|
|
||||||
autoOpen: false,
|
|
||||||
height: 340,
|
|
||||||
width: 350,
|
|
||||||
modal: true,
|
|
||||||
buttons: {
|
|
||||||
"Send": function() {
|
|
||||||
var intent = collectIntent();
|
|
||||||
|
|
||||||
console.log(intent);
|
|
||||||
|
|
||||||
if(iwc.util.validateIntent(intent)) {
|
|
||||||
iwcClient.publish(intent);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert("Intent not valid! ");
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
Export: function() {
|
|
||||||
var intent = collectIntent();
|
|
||||||
var istr = JSON.stringify(intent);
|
|
||||||
console.log(istr);
|
|
||||||
$("#intsnip").html(istr);
|
|
||||||
$("#exint").dialog("open");
|
|
||||||
},
|
|
||||||
Cancel: function() {
|
|
||||||
$(this).dialog('close');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close: function(){
|
|
||||||
//$(this).dialog('close');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
gadgets.window.adjustHeight();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).ready(init());
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<button id="sendb">Send Intent</button> <button id="clearb">Clear List</button>
|
|
||||||
<h1>Received Intents</h1>
|
|
||||||
<div id="accordion">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id='sendintent' title='Send Intent'>
|
|
||||||
<table id='pub_form'>
|
|
||||||
<tr><td class='ui-state-default'>Publisher</td><td class='input'><input id='pub_publisher' type='text' value='me'/></td></tr>
|
|
||||||
<tr><td class='ui-state-default'>Source</td><td class='input'><input id='pub_source' type='text' value='http://widget.org/sender.xml'/></td></tr>
|
|
||||||
<tr><td class='ui-state-default'>Component</td><td class='input'><input id='pub_component' type='text'/></td></tr>
|
|
||||||
<tr><td class='ui-state-default'>Action</td><td class='input'><input id='pub_action' type='text' value='ACTION_UPDATE'/></td></tr>
|
|
||||||
<tr><td class='ui-state-default'>Data</td><td class='input'><input id='pub_data' type='text' value='http://example.org/some/data'/></td></tr>
|
|
||||||
<tr><td class='ui-state-default'>Data Type</td><td class='input'><input id='pub_datatype' type='text' value='text/plain'/></td></tr>
|
|
||||||
<tr><td class='ui-state-default'>Flags</td><td class='input'><input id='pub_flags' type='text' value='PUBLISH_GLOBAL'/></td></tr>
|
|
||||||
<tr><td class='ui-state-default'>Categories</td><td class='input'><input id='pub_categories' type='text' value='cat1,cat2'/></td></tr>
|
|
||||||
<!-- <tr><td class='ui-state-default'>Extras</td><td class='input'><input id='pub_extras' type='text' value='{"key":"value"}'/></td></tr> -->
|
|
||||||
<tr><td class='ui-state-default'>Extras</td><td class='input'><textarea id='pub_extras' value='{"key":"value"}'/></td></tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="exint" title="Exported Intent JSON">
|
|
||||||
Copy the snippet below to your code to specify a respective intent message.
|
|
||||||
<p id="intsnip"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
]]>
|
|
||||||
</Content>
|
|
||||||
</Module>
|
|
||||||
@@ -1,371 +0,0 @@
|
|||||||
//get the iwc.Client class def.
|
|
||||||
/*
|
|
||||||
iwc = iwc || {};
|
|
||||||
iwc.Client = iwc.Client || {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a function to set the compnent name of the iwc.Client class.<br/>
|
|
||||||
* This component name is for filtering incoming intent at the iwc.Client. The intent can be further processed
|
|
||||||
* only when the intent.component attribute matches the component name of the iwc.Client or the intent.component is an empty string(pseudo broadcast).
|
|
||||||
* @param componentName The component name
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
iwc.Client.prototype.setComponentName = function(componentName){
|
|
||||||
this._componentName = componentName;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
DUIClient = function(){
|
|
||||||
//in role framework the parent div of the widget ifr is IDed as "widget-{widgetId}-body" sth. like this
|
|
||||||
var _widgetId = parent.document.getElementById(self.frameElement.id).parentNode.id.split("-")[1];
|
|
||||||
var that = this;
|
|
||||||
var _iwcClient = new iwc.Client(["*"]);
|
|
||||||
_iwcClient._componentName = "duiclient-"+_widgetId;
|
|
||||||
|
|
||||||
this.externalCallback = function(intent){};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The target function when the intent is for updating widget state request
|
|
||||||
*/
|
|
||||||
this._onUpdateState = function(intent){
|
|
||||||
var isForMigration = intent.extras.isForMigration;
|
|
||||||
if (isForMigration)
|
|
||||||
this.finishMigration(intent);
|
|
||||||
else
|
|
||||||
this.updateState(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.getIwcClient = function(){
|
|
||||||
return _iwcClient;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* The target function when the intent is for getting the current widget state.<br/>
|
|
||||||
* The intent.extras object here is always a Json object.
|
|
||||||
*/
|
|
||||||
this._onGetWidgetState = function(intent){
|
|
||||||
var target = null;
|
|
||||||
var forMigration = false;
|
|
||||||
if (intent.extras.target != null){
|
|
||||||
target = intent.extras.target;
|
|
||||||
forMigration = true;
|
|
||||||
}
|
|
||||||
var states = this.getWidgetState(forMigration);
|
|
||||||
|
|
||||||
var resIntent = {};
|
|
||||||
if (forMigration)
|
|
||||||
resIntent = {
|
|
||||||
"action": "DUI_WS_MIG",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": "duimanager",
|
|
||||||
"data":"",
|
|
||||||
"dataType":"",
|
|
||||||
"extras":{"target": target, "widgetId": _widgetId, "widgetStates": states}
|
|
||||||
};
|
|
||||||
else
|
|
||||||
resIntent = {
|
|
||||||
"action": "DUI_WS",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": intent.sender,
|
|
||||||
"data":"",
|
|
||||||
"dataType":"",
|
|
||||||
"extras":{"widgetId": _widgetId, "widgetStates": states}
|
|
||||||
};
|
|
||||||
|
|
||||||
_iwcClient.publish(resIntent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The target function when the intent is to inform a change in the scope of the application
|
|
||||||
*/
|
|
||||||
this._onAppStateChange = function(intent){
|
|
||||||
this.changeWithApp(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The target function when the intent is to inform a migration of this widget is waiting to be taken place
|
|
||||||
*/
|
|
||||||
this._prepareMigration = function(intent){
|
|
||||||
console.log("do sth before the widget is removed");
|
|
||||||
this.prepareMigration();
|
|
||||||
};
|
|
||||||
|
|
||||||
this._logOff = function(intent){
|
|
||||||
var states = this.getWidgetState(false);
|
|
||||||
resIntent = {
|
|
||||||
"action": "DUI_WS_LOGOFF",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": "duimanager",
|
|
||||||
"data":"",
|
|
||||||
"dataType":"",
|
|
||||||
"extras":{"widgetId": _widgetId, "widgetStates": states}
|
|
||||||
};
|
|
||||||
|
|
||||||
_iwcClient.publish(resIntent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The intent dispatcher and the callback function connected to the private field of iwc.Client.onIntent.<br/>
|
|
||||||
* This function is called once an intent is received by the iwc.Client and passed the first level filter of the iwc.Client.<br/>
|
|
||||||
* @param intent The incoming intent. Technically all intents will come, the filter of the iwc.Client class is weak...
|
|
||||||
*/
|
|
||||||
var _iwcCallback = function(intent){
|
|
||||||
that.externalCallback(intent);
|
|
||||||
//does not accept global intents(global intents are processed by normal iwc.Client, normal iwc.Proxy and DUI manager)
|
|
||||||
//does not accept intents that are not categorized as "DUI"
|
|
||||||
if ((typeof intent.flags != "undefined" && intent.flags.indexOf("PUBLISH_GLOBAL")!=-1)
|
|
||||||
|| typeof intent.categories == "undefined" || intent.categories.indexOf("DUI") == -1)
|
|
||||||
return;
|
|
||||||
//then does not accept intents for other widgets
|
|
||||||
//if the widget id is undefined here, this is an DUI intent from the DUI manager for all involved widget, e.g. application state changed
|
|
||||||
var action = intent.action;
|
|
||||||
if (typeof intent.extras.widgetId != "undefined" && intent.extras.widgetId == _widgetId){
|
|
||||||
if (action == "DUI_UPDATE_STATE"){
|
|
||||||
that._onUpdateState(intent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (action == "DUI_GET_WS"){
|
|
||||||
that._onGetWidgetState(intent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (action == "DUI_PRE_MIG"){
|
|
||||||
that._prepareMigration(intent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}else if (typeof intent.extras.widgetId == "undefined"){
|
|
||||||
if (action == "DUI_LOG_OFF"){
|
|
||||||
that._logOff(intent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (action == "DUI_APP_CHANGE"){
|
|
||||||
that._onAppStateChange(intent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (action == "DUI_REG_CLIENT"){
|
|
||||||
that.initOK();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (action == "DUI_AS"){
|
|
||||||
that.onAppState(intent.extras.appStates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_iwcClient.connect(_iwcCallback);
|
|
||||||
|
|
||||||
//remember to bind(this) the function when override
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function is called when the dui manager wants the widget states.<br/>
|
|
||||||
* <strong>Notice</strong>: avoid putting complex data and data structure to the state value, the browser and Java JSON encoder and parser might cause inconsistent input and output.
|
|
||||||
* @param isForMigration A boolean. True if special state for migration is needed otherwise not.
|
|
||||||
* @returns an object containing the widget states, e.g. {"selectIndex":1, "phaseNum":2, "textinput":"iamatextvalueinatextinput"}
|
|
||||||
*/
|
|
||||||
this.getWidgetState = function(isForMigration){
|
|
||||||
console.log("the widget collects it is state and return, overwrite it");
|
|
||||||
var states = {};
|
|
||||||
return states;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function is called when there detected a application state change at the dui manager and the manager informs the widget about the change.<br/>
|
|
||||||
* Override this function to apply changes to the widget according to the valuable application state changes.<br/>
|
|
||||||
* @param intent intent The infos are in intent.extras object e.g. intent.extras = {"oldStates":{}, "newStates":{"statename":value, "state2":value2}}. the property 'oldStates' can be null if the space has not set app state ever before.
|
|
||||||
*/
|
|
||||||
this.changeWithApp = function(intent){
|
|
||||||
//sample
|
|
||||||
var oldStates = intent.extras.oldStates;
|
|
||||||
var newStates = intent.extras.newStates;
|
|
||||||
console.log(oldStates);
|
|
||||||
console.log(newStates);
|
|
||||||
console.log("the widget may need to change something following the whole app");
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function is called right before a migration for this widget and the widget state is already saved to the server in previous migration phases.<br/>
|
|
||||||
* And it is the last chance to perform any moves before the widget is removed from current web page.<br/>
|
|
||||||
* Override this method to perform state update for each different widget.<br/>
|
|
||||||
* <strong>AND DO REMEMBER TO CALL {@link DUIClient#prepareMigDone} AT THE END OF THIS FUNCTION!</strong>
|
|
||||||
*/
|
|
||||||
this.prepareMigration = function(){
|
|
||||||
//e.g. ..... just a joke....
|
|
||||||
/*
|
|
||||||
if (confirm("you sure to sign out?..."))
|
|
||||||
parent.location = parent.location.protocol + "//" + parent.location.host + "/:authentication?return=&action=signout";
|
|
||||||
console.log("the migration is at hand, the widget may need to do sth special before it is removed from the role widget container e.g. disconnect from the lasServer etc.");
|
|
||||||
*/
|
|
||||||
this.prepareMigDone();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function is called when the dui manager asks the widget to update its states.<br/>
|
|
||||||
* Compared to the function DUIClient.finishMigration(), this is a typical normal state update for active widget on presence.<br/>
|
|
||||||
* This method will be called as a callback for DUIClient#requireWidgetState(); or DUIClient#initOK() when it is not a migration.
|
|
||||||
* Override this method to perform state update for each different widget.
|
|
||||||
* @param intent The Intent object that contains infos of required widget states, the infos are in intent.extras.widgetStates e.g. {"state1":value1,"state2":value2}.
|
|
||||||
* The object might contain appStates as well if there is any application state, get it in intent.extras.appStates e.g. {"appstate1":value1,"appstate2":value2}.
|
|
||||||
*/
|
|
||||||
this.updateState = function(intent){
|
|
||||||
var states = {};
|
|
||||||
states = intent.extras.widgetStates;
|
|
||||||
var appStates = intent.extras.appStates;
|
|
||||||
console.log(states);
|
|
||||||
if (typeof appStates != "undefined")
|
|
||||||
console.log(appStates);
|
|
||||||
console.log("update the widget state, widget need to overwrite it");
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function is called to finish the Migration and update the widget state.<br/>
|
|
||||||
* Compared to the method DUIClient.updateState(), this method is a special widget state update for the widget that has just migrated.<br/>
|
|
||||||
* Override this method to perform finishing moves for each different widget.
|
|
||||||
* @param intent The Intent object that contains infos to complete the migration, the infos are in intent.extras.states e.g. {"state1":value1, "state2":value2}.
|
|
||||||
* The object might contain appStates as well if there is any application state, get it in intent.extras.appStates e.g. {"appstate1":value1,"appstate2":value2}.
|
|
||||||
*/
|
|
||||||
this.finishMigration = function(intent){
|
|
||||||
var states = {};
|
|
||||||
states = intent.extras.widgetStates;
|
|
||||||
var appStates = intent.extras.appStates;
|
|
||||||
console.log(states);
|
|
||||||
if (typeof appStates != "undefined")
|
|
||||||
console.log(appStates);
|
|
||||||
console.log("the migration is done, the widget may need to perform special inits before update the widget state e.g. login to the lasServer again.");
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function to signal the dui manager that the preparation for the migration is ready on this widget.<br/>
|
|
||||||
* This function should be called at the end of the overwritten function {@link DUIClient#prepareMigration}<br/>
|
|
||||||
* Do not override this method unless there is really an unstoppable reason.
|
|
||||||
*/
|
|
||||||
this.prepareMigDone = function(){
|
|
||||||
//prepared and send OK response to DUIMgr
|
|
||||||
var intent = {
|
|
||||||
"component": "duimanager",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"action": "DUI_PRE_MIG_OK",
|
|
||||||
"data": "",
|
|
||||||
"dataType": "",
|
|
||||||
"extras": {"widgetId": _widgetId}
|
|
||||||
};
|
|
||||||
_iwcClient.publish(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function to call the DUI manager to save the widget state on the server.<br/>
|
|
||||||
* Do not override this method unless there is really an unstoppable reason.
|
|
||||||
* @param states An array of widget state object {"stateName": stateValue}
|
|
||||||
*/
|
|
||||||
this.saveWidgetState = function(){
|
|
||||||
var states = this.getWidgetState(false);
|
|
||||||
var intent = {
|
|
||||||
"action": "DUI_SAVE_WS",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": "duimanager",// the overwritten dui manager from the iwc.Proxy should have the _componentName set to "duimanager"
|
|
||||||
"data":"",
|
|
||||||
"dataType":"",
|
|
||||||
"extras":{"widgetStates":states, "widgetId": _widgetId}
|
|
||||||
};
|
|
||||||
_iwcClient.publish(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An open interface to send any intent
|
|
||||||
*/
|
|
||||||
this.sendIntent = function(intent){
|
|
||||||
//or to send the intent to "duimanager"
|
|
||||||
_iwcClient.publish(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function asks the framework for the states stored on the server.
|
|
||||||
* Do not override it.
|
|
||||||
*/
|
|
||||||
this.requireWidgetState = function(){
|
|
||||||
var intent = {
|
|
||||||
"action": "DUI_REQ_WS",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": "duimanager",// the overwritten dui manager from the iwc.Proxy should have the _componentName set to "duimanager"
|
|
||||||
"data":"",
|
|
||||||
"dataType":"",
|
|
||||||
"extras":{"widgetId": _widgetId}
|
|
||||||
};
|
|
||||||
_iwcClient.publish(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store the global app state
|
|
||||||
* @param states the app state to be stored e.g. {"state1":value1, "state2":value2}
|
|
||||||
*/
|
|
||||||
this.setAppState = function(states){
|
|
||||||
var intent = {
|
|
||||||
"action": "DUI_SET_AS",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": "duimanager",// the overwritten dui manager from the iwc.Proxy should have the _componentName set to "duimanager"
|
|
||||||
"data":"",
|
|
||||||
"dataType":"",
|
|
||||||
"extras":{"states": states}
|
|
||||||
};
|
|
||||||
_iwcClient.publish(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ask the dui manager for the app state.
|
|
||||||
*/
|
|
||||||
this.getAppState = function(){
|
|
||||||
var intent = {
|
|
||||||
"action": "DUI_GET_AS",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": "duimanager",// the overwritten dui manager from the iwc.Proxy should have the _componentName set to "duimanager"
|
|
||||||
"data":"",
|
|
||||||
"dataType":"",
|
|
||||||
};
|
|
||||||
_iwcClient.publish(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override this function to do something when the requested app state comes.
|
|
||||||
* @param appStates the json format of the app state:{"name1": value1, "name2": value2};
|
|
||||||
*/
|
|
||||||
this.onAppState = function(appStates){};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* call this function to register the duiclient to duimanager after all things are OK
|
|
||||||
*/
|
|
||||||
this.initOK = function(){
|
|
||||||
var okIntent = {
|
|
||||||
"action": "DUI_CLIENT_OK",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": "duimanager",// the overwritten dui manager from the iwc.Proxy should have the _componentName set to "duimanager"
|
|
||||||
"data":"",
|
|
||||||
"dataType":"",
|
|
||||||
"extras":{"widgetId": _widgetId}
|
|
||||||
};
|
|
||||||
|
|
||||||
_iwcClient.publish(okIntent);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* publish the intent in the domain of the user only
|
|
||||||
*/
|
|
||||||
this.publishToUser = function(intent){
|
|
||||||
var wrap = {
|
|
||||||
"action": "DUI_PUB_USER",
|
|
||||||
"categories": ["DUI"],
|
|
||||||
"component": "duimanager",
|
|
||||||
"data": JSON.stringify(intent),
|
|
||||||
"dataType": "application/json",
|
|
||||||
"extras": {}
|
|
||||||
};
|
|
||||||
_iwcClient.publish(intent);
|
|
||||||
_iwcClient.publish(wrap);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* register the call back function of the widget to the DUI client.
|
|
||||||
*/
|
|
||||||
this.connect = function(callback){
|
|
||||||
this.externalCallback = callback;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// reminder to myself:.... the callback funcs injected into this DUIClient need to bind()
|
|
||||||
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,115 +0,0 @@
|
|||||||
var createIwcConnector;
|
|
||||||
|
|
||||||
createIwcConnector = function(callback) {
|
|
||||||
var IwcConnector, duiClient, get_HB_intent, init, iwcHandler, received_HB;
|
|
||||||
iwcHandler = {};
|
|
||||||
duiClient = new DUIClient();
|
|
||||||
duiClient.connect(function(intent) {
|
|
||||||
var _ref;
|
|
||||||
return (_ref = iwcHandler[intent.action]) != null ? _ref.map(function(f) {
|
|
||||||
return setTimeout(function() {
|
|
||||||
return f(intent);
|
|
||||||
}, 0);
|
|
||||||
}) : void 0;
|
|
||||||
});
|
|
||||||
duiClient.initOK();
|
|
||||||
received_HB = null;
|
|
||||||
IwcConnector = (function() {
|
|
||||||
function IwcConnector(engine, HB, execution_listener, yatta) {
|
|
||||||
var receive_, sendHistoryBuffer, send_;
|
|
||||||
this.engine = engine;
|
|
||||||
this.HB = HB;
|
|
||||||
this.execution_listener = execution_listener;
|
|
||||||
this.yatta = yatta;
|
|
||||||
this.duiClient = duiClient;
|
|
||||||
this.iwcHandler = iwcHandler;
|
|
||||||
send_ = (function(_this) {
|
|
||||||
return function(o) {
|
|
||||||
return _this.send(o);
|
|
||||||
};
|
|
||||||
})(this);
|
|
||||||
this.execution_listener.push(send_);
|
|
||||||
receive_ = (function(_this) {
|
|
||||||
return function(intent) {
|
|
||||||
var o;
|
|
||||||
o = intent.extras;
|
|
||||||
return _this.receive(o);
|
|
||||||
};
|
|
||||||
})(this);
|
|
||||||
this.iwcHandler["Yatta_new_operation"] = [receive_];
|
|
||||||
if (received_HB != null) {
|
|
||||||
this.engine.applyOpsCheckDouble(received_HB);
|
|
||||||
}
|
|
||||||
sendHistoryBuffer = (function(_this) {
|
|
||||||
return function() {
|
|
||||||
var json;
|
|
||||||
json = {
|
|
||||||
HB: _this.yatta.getHistoryBuffer()._encode()
|
|
||||||
};
|
|
||||||
return _this.sendIwcIntent("Yatta_push_HB_element", json);
|
|
||||||
};
|
|
||||||
})(this);
|
|
||||||
this.iwcHandler["Yatta_get_HB_element"] = [sendHistoryBuffer];
|
|
||||||
}
|
|
||||||
|
|
||||||
IwcConnector.prototype.send = function(o) {
|
|
||||||
if (o.uid.creator === this.HB.getUserId() && (typeof o.uid.op_number !== "string")) {
|
|
||||||
return this.sendIwcIntent("Yatta_new_operation", o);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
IwcConnector.prototype.receive = function(o) {
|
|
||||||
if (o.uid.creator !== this.HB.getUserId()) {
|
|
||||||
return this.engine.applyOp(o);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
IwcConnector.prototype.sendIwcIntent = function(action_name, content) {
|
|
||||||
var intent;
|
|
||||||
intent = {
|
|
||||||
action: action_name,
|
|
||||||
component: "",
|
|
||||||
data: "",
|
|
||||||
dataType: "",
|
|
||||||
extras: content
|
|
||||||
};
|
|
||||||
return this.duiClient.sendIntent(intent);
|
|
||||||
};
|
|
||||||
|
|
||||||
return IwcConnector;
|
|
||||||
|
|
||||||
})();
|
|
||||||
get_HB_intent = {
|
|
||||||
action: "Yatta_get_HB_element",
|
|
||||||
component: "",
|
|
||||||
data: "",
|
|
||||||
dataType: "",
|
|
||||||
extras: {}
|
|
||||||
};
|
|
||||||
init = function() {
|
|
||||||
var is_initialized, receiveHB;
|
|
||||||
duiClient.sendIntent(get_HB_intent);
|
|
||||||
is_initialized = false;
|
|
||||||
receiveHB = function(json) {
|
|
||||||
var proposed_user_id;
|
|
||||||
proposed_user_id = duiClient.getIwcClient()._componentName;
|
|
||||||
received_HB = json != null ? json.extras.HB : void 0;
|
|
||||||
if (!is_initialized) {
|
|
||||||
is_initialized = true;
|
|
||||||
return callback(IwcConnector, proposed_user_id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
iwcHandler["Yatta_push_HB_element"] = [receiveHB];
|
|
||||||
return setTimeout(receiveHB, 0);
|
|
||||||
};
|
|
||||||
setTimeout(init, Math.random() * 0);
|
|
||||||
return void 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = createIwcConnector;
|
|
||||||
|
|
||||||
if (typeof window !== "undefined" && window !== null) {
|
|
||||||
window.createConnector = createIwcConnector;
|
|
||||||
}
|
|
||||||
|
|
||||||
//# sourceMappingURL=IwcConnector.js.map
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"file": "IwcConnector.js",
|
|
||||||
"sourceRoot": "../../../lib/Connectors/",
|
|
||||||
"sources": [
|
|
||||||
"IwcConnector.coffee"
|
|
||||||
],
|
|
||||||
"names": [],
|
|
||||||
"mappings": "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"
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
var _;
|
|
||||||
|
|
||||||
_ = require("underscore");
|
|
||||||
|
|
||||||
module.exports = function(user_list) {
|
|
||||||
var TestConnector;
|
|
||||||
return TestConnector = (function() {
|
|
||||||
function TestConnector(engine, HB, execution_listener) {
|
|
||||||
var appliedOperationsListener, send_;
|
|
||||||
this.engine = engine;
|
|
||||||
this.HB = HB;
|
|
||||||
this.execution_listener = execution_listener;
|
|
||||||
send_ = (function(_this) {
|
|
||||||
return function(o) {
|
|
||||||
return _this.send(o);
|
|
||||||
};
|
|
||||||
})(this);
|
|
||||||
this.execution_listener.push(send_);
|
|
||||||
this.applied_operations = [];
|
|
||||||
appliedOperationsListener = (function(_this) {
|
|
||||||
return function(o) {
|
|
||||||
return _this.applied_operations.push(o);
|
|
||||||
};
|
|
||||||
})(this);
|
|
||||||
this.execution_listener.push(appliedOperationsListener);
|
|
||||||
if (!((user_list != null ? user_list.length : void 0) === 0)) {
|
|
||||||
this.engine.applyOps(user_list[0].getHistoryBuffer()._encode());
|
|
||||||
}
|
|
||||||
this.unexecuted = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
TestConnector.prototype.getOpsInExecutionOrder = function() {
|
|
||||||
return this.applied_operations;
|
|
||||||
};
|
|
||||||
|
|
||||||
TestConnector.prototype.send = function(o) {
|
|
||||||
var user, _i, _len, _results;
|
|
||||||
if ((o.uid.creator === this.HB.getUserId()) && (typeof o.uid.op_number !== "string")) {
|
|
||||||
_results = [];
|
|
||||||
for (_i = 0, _len = user_list.length; _i < _len; _i++) {
|
|
||||||
user = user_list[_i];
|
|
||||||
if (user.getUserId() !== this.HB.getUserId()) {
|
|
||||||
_results.push(user.getConnector().receive(o));
|
|
||||||
} else {
|
|
||||||
_results.push(void 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TestConnector.prototype.receive = function(o) {
|
|
||||||
var _base, _name;
|
|
||||||
if ((_base = this.unexecuted)[_name = o.uid.creator] == null) {
|
|
||||||
_base[_name] = [];
|
|
||||||
}
|
|
||||||
return this.unexecuted[o.uid.creator].push(o);
|
|
||||||
};
|
|
||||||
|
|
||||||
TestConnector.prototype.flushOne = function(user) {
|
|
||||||
var _ref;
|
|
||||||
if (((_ref = this.unexecuted[user]) != null ? _ref.length : void 0) > 0) {
|
|
||||||
return this.engine.applyOp(this.unexecuted[user].shift());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TestConnector.prototype.flushOneRandom = function() {
|
|
||||||
return this.flushOne(_.random(0, user_list.length - 1));
|
|
||||||
};
|
|
||||||
|
|
||||||
TestConnector.prototype.flushAll = function() {
|
|
||||||
var n, ops, _ref;
|
|
||||||
_ref = this.unexecuted;
|
|
||||||
for (n in _ref) {
|
|
||||||
ops = _ref[n];
|
|
||||||
this.engine.applyOps(ops);
|
|
||||||
}
|
|
||||||
return this.unexecuted = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
return TestConnector;
|
|
||||||
|
|
||||||
})();
|
|
||||||
};
|
|
||||||
|
|
||||||
//# sourceMappingURL=TestConnector.js.map
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"file": "TestConnector.js",
|
|
||||||
"sourceRoot": "../../../lib/Connectors/",
|
|
||||||
"sources": [
|
|
||||||
"TestConnector.coffee"
|
|
||||||
],
|
|
||||||
"names": [],
|
|
||||||
"mappings": "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"
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
var Engine;
|
|
||||||
|
|
||||||
Engine = (function() {
|
|
||||||
function Engine(HB, parser) {
|
|
||||||
this.HB = HB;
|
|
||||||
this.parser = parser;
|
|
||||||
this.unprocessed_ops = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
Engine.prototype.parseOperation = function(json) {
|
|
||||||
var typeParser;
|
|
||||||
typeParser = this.parser[json.type];
|
|
||||||
if (typeParser != null) {
|
|
||||||
return typeParser(json);
|
|
||||||
} else {
|
|
||||||
throw new Error("You forgot to specify a parser for type " + json.type + ". The message is " + (JSON.stringify(json)) + ".");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Engine.prototype.applyOpsBundle = function(ops_json) {
|
|
||||||
var o, ops, _i, _j, _k, _len, _len1, _len2;
|
|
||||||
ops = [];
|
|
||||||
for (_i = 0, _len = ops_json.length; _i < _len; _i++) {
|
|
||||||
o = ops_json[_i];
|
|
||||||
ops.push(this.parseOperation(o));
|
|
||||||
}
|
|
||||||
for (_j = 0, _len1 = ops.length; _j < _len1; _j++) {
|
|
||||||
o = ops[_j];
|
|
||||||
this.HB.addOperation(o);
|
|
||||||
}
|
|
||||||
for (_k = 0, _len2 = ops.length; _k < _len2; _k++) {
|
|
||||||
o = ops[_k];
|
|
||||||
if (!o.execute()) {
|
|
||||||
this.unprocessed_ops.push(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.tryUnprocessed();
|
|
||||||
};
|
|
||||||
|
|
||||||
Engine.prototype.applyOpsCheckDouble = function(ops_json) {
|
|
||||||
var o, _i, _len, _results;
|
|
||||||
_results = [];
|
|
||||||
for (_i = 0, _len = ops_json.length; _i < _len; _i++) {
|
|
||||||
o = ops_json[_i];
|
|
||||||
if (this.HB.getOperation(o.uid) != null) {
|
|
||||||
_results.push(this.applyOp(o));
|
|
||||||
} else {
|
|
||||||
_results.push(void 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
};
|
|
||||||
|
|
||||||
Engine.prototype.applyOps = function(ops_json) {
|
|
||||||
var o, _i, _len, _results;
|
|
||||||
_results = [];
|
|
||||||
for (_i = 0, _len = ops_json.length; _i < _len; _i++) {
|
|
||||||
o = ops_json[_i];
|
|
||||||
_results.push(this.applyOp(o));
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
};
|
|
||||||
|
|
||||||
Engine.prototype.applyOp = function(op_json) {
|
|
||||||
var o;
|
|
||||||
o = this.parseOperation(op_json);
|
|
||||||
this.HB.addToCounter(o);
|
|
||||||
if (!o.execute()) {
|
|
||||||
this.unprocessed_ops.push(o);
|
|
||||||
} else {
|
|
||||||
this.HB.addOperation(o);
|
|
||||||
}
|
|
||||||
return this.tryUnprocessed();
|
|
||||||
};
|
|
||||||
|
|
||||||
Engine.prototype.tryUnprocessed = function() {
|
|
||||||
var old_length, op, unprocessed, _i, _len, _ref, _results;
|
|
||||||
_results = [];
|
|
||||||
while (true) {
|
|
||||||
old_length = this.unprocessed_ops.length;
|
|
||||||
unprocessed = [];
|
|
||||||
_ref = this.unprocessed_ops;
|
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
||||||
op = _ref[_i];
|
|
||||||
if (!op.execute()) {
|
|
||||||
unprocessed.push(op);
|
|
||||||
} else {
|
|
||||||
this.HB.addOperation(op);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.unprocessed_ops = unprocessed;
|
|
||||||
if (this.unprocessed_ops.length === old_length) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
_results.push(void 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
};
|
|
||||||
|
|
||||||
return Engine;
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
module.exports = Engine;
|
|
||||||
|
|
||||||
//# sourceMappingURL=Engine.js.map
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"file": "Engine.js",
|
|
||||||
"sourceRoot": "../../lib/",
|
|
||||||
"sources": [
|
|
||||||
"Engine.coffee"
|
|
||||||
],
|
|
||||||
"names": [],
|
|
||||||
"mappings": "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"
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
var Engine, HistoryBuffer, JsonYatta, json_types_uninitialized;
|
|
||||||
|
|
||||||
json_types_uninitialized = require("../Types/JsonTypes.coffee");
|
|
||||||
|
|
||||||
HistoryBuffer = require("../HistoryBuffer.coffee");
|
|
||||||
|
|
||||||
Engine = require("../Engine.coffee");
|
|
||||||
|
|
||||||
JsonYatta = (function() {
|
|
||||||
function JsonYatta(user_id, Connector) {
|
|
||||||
var first_word, json_types;
|
|
||||||
this.HB = new HistoryBuffer(user_id);
|
|
||||||
json_types = json_types_uninitialized(this.HB);
|
|
||||||
this.engine = new Engine(this.HB, json_types.parser);
|
|
||||||
this.connector = new Connector(this.engine, this.HB, json_types.execution_listener, this);
|
|
||||||
first_word = new json_types.types.JsonType(this.HB.getReservedUniqueIdentifier());
|
|
||||||
this.HB.addOperation(first_word).execute();
|
|
||||||
this.root_element = first_word;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonYatta.prototype.getRootElement = function() {
|
|
||||||
return this.root_element;
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonYatta.prototype.getEngine = function() {
|
|
||||||
return this.engine;
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonYatta.prototype.getConnector = function() {
|
|
||||||
return this.connector;
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonYatta.prototype.getHistoryBuffer = function() {
|
|
||||||
return this.HB;
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonYatta.prototype.setMutableDefault = function(mutable) {
|
|
||||||
return this.root_element.setMutableDefault(mutable);
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonYatta.prototype.getUserId = function() {
|
|
||||||
return this.HB.getUserId();
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonYatta.prototype.val = function(name, content, mutable) {
|
|
||||||
return this.root_element.val(name, content, mutable);
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperty(JsonYatta.prototype, 'value', {
|
|
||||||
get: function() {
|
|
||||||
return this.root_element.value;
|
|
||||||
},
|
|
||||||
set: function(o) {
|
|
||||||
var o_name, o_obj, _results;
|
|
||||||
if (o.constructor === {}.constructor) {
|
|
||||||
_results = [];
|
|
||||||
for (o_name in o) {
|
|
||||||
o_obj = o[o_name];
|
|
||||||
_results.push(this.val(o_name, o_obj, 'immutable'));
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
} else {
|
|
||||||
throw new Error("You must only set Object values!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return JsonYatta;
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (typeof window !== "undefined" && window !== null) {
|
|
||||||
window.JsonYatta = JsonYatta;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = JsonYatta;
|
|
||||||
|
|
||||||
//# sourceMappingURL=JsonYatta.js.map
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"file": "JsonYatta.js",
|
|
||||||
"sourceRoot": "../../../lib/Frameworks/",
|
|
||||||
"sources": [
|
|
||||||
"JsonYatta.coffee"
|
|
||||||
],
|
|
||||||
"names": [],
|
|
||||||
"mappings": "AACA,IAAA,0DAAA;;AAAA,wBAAA,GAA2B,OAAA,CAAQ,2BAAR,CAA3B,CAAA;;AAAA,aACA,GAAgB,OAAA,CAAQ,yBAAR,CADhB,CAAA;;AAAA,MAEA,GAAS,OAAA,CAAQ,kBAAR,CAFT,CAAA;;AAAA;AAiBe,EAAA,mBAAC,OAAD,EAAU,SAAV,GAAA;AACX,QAAA,sBAAA;AAAA,IAAA,IAAC,CAAA,EAAD,GAAU,IAAA,aAAA,CAAc,OAAd,CAAV,CAAA;AAAA,IACA,UAAA,GAAa,wBAAA,CAAyB,IAAC,CAAA,EAA1B,CADb,CAAA;AAAA,IAEA,IAAC,CAAA,MAAD,GAAc,IAAA,MAAA,CAAO,IAAC,CAAA,EAAR,EAAY,UAAU,CAAC,MAAvB,CAFd,CAAA;AAAA,IAGA,IAAC,CAAA,SAAD,GAAiB,IAAA,SAAA,CAAU,IAAC,CAAA,MAAX,EAAmB,IAAC,CAAA,EAApB,EAAwB,UAAU,CAAC,kBAAnC,EAAuD,IAAvD,CAHjB,CAAA;AAAA,IAKA,UAAA,GAAiB,IAAA,UAAU,CAAC,KAAK,CAAC,QAAjB,CAA0B,IAAC,CAAA,EAAE,CAAC,2BAAJ,CAAA,CAA1B,CALjB,CAAA;AAAA,IAMA,IAAC,CAAA,EAAE,CAAC,YAAJ,CAAiB,UAAjB,CAA4B,CAAC,OAA7B,CAAA,CANA,CAAA;AAAA,IAOA,IAAC,CAAA,YAAD,GAAgB,UAPhB,CADW;EAAA,CAAb;;AAAA,sBAaA,cAAA,GAAgB,SAAA,GAAA;WACd,IAAC,CAAA,aADa;EAAA,CAbhB,CAAA;;AAAA,sBAmBA,SAAA,GAAW,SAAA,GAAA;WACT,IAAC,CAAA,OADQ;EAAA,CAnBX,CAAA;;AAAA,sBAyBA,YAAA,GAAc,SAAA,GAAA;WACZ,IAAC,CAAA,UADW;EAAA,CAzBd,CAAA;;AAAA,sBA+BA,gBAAA,GAAkB,SAAA,GAAA;WAChB,IAAC,CAAA,GADe;EAAA,CA/BlB,CAAA;;AAAA,sBAqCA,iBAAA,GAAmB,SAAC,OAAD,GAAA;WAChB,IAAC,CAAA,YAAY,CAAC,iBAAd,CAAgC,OAAhC,EADgB;EAAA,CArCnB,CAAA;;AAAA,sBA6CA,SAAA,GAAW,SAAA,GAAA;WACT,IAAC,CAAA,EAAE,CAAC,SAAJ,CAAA,EADS;EAAA,CA7CX,CAAA;;AAAA,sBAmDA,GAAA,GAAM,SAAC,IAAD,EAAO,OAAP,EAAgB,OAAhB,GAAA;WACJ,IAAC,CAAA,YAAY,CAAC,GAAd,CAAkB,IAAlB,EAAwB,OAAxB,EAAiC,OAAjC,EADI;EAAA,CAnDN,CAAA;;AAAA,EAyDA,MAAM,CAAC,cAAP,CAAsB,SAAS,CAAC,SAAhC,EAA2C,OAA3C,EACE;AAAA,IAAA,GAAA,EAAM,SAAA,GAAA;aAAG,IAAC,CAAA,YAAY,CAAC,MAAjB;IAAA,CAAN;AAAA,IACA,GAAA,EAAM,SAAC,CAAD,GAAA;AACJ,UAAA,uBAAA;AAAA,MAAA,IAAG,CAAC,CAAC,WAAF,KAAiB,EAAE,CAAC,WAAvB;AACE;aAAA,WAAA;4BAAA;AACE,wBAAA,IAAC,CAAA,GAAD,CAAK,MAAL,EAAa,KAAb,EAAoB,WAApB,EAAA,CADF;AAAA;wBADF;OAAA,MAAA;AAIE,cAAU,IAAA,KAAA,CAAM,kCAAN,CAAV,CAJF;OADI;IAAA,CADN;GADF,CAzDA,CAAA;;mBAAA;;IAjBF,CAAA;;;EAkFA,MAAM,CAAE,SAAR,GAAoB;CAlFpB;;AAAA,MAmFM,CAAC,OAAP,GAAiB,SAnFjB,CAAA"
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
var Engine, HistoryBuffer, TextYatta, text_types_uninitialized;
|
|
||||||
|
|
||||||
text_types_uninitialized = require("../Types/TextTypes.coffee");
|
|
||||||
|
|
||||||
HistoryBuffer = require("../HistoryBuffer.coffee");
|
|
||||||
|
|
||||||
Engine = require("../Engine.coffee");
|
|
||||||
|
|
||||||
TextYatta = (function() {
|
|
||||||
function TextYatta(user_id, Connector) {
|
|
||||||
var first_word, text_types;
|
|
||||||
this.HB = new HistoryBuffer(user_id);
|
|
||||||
text_types = text_types_uninitialized(this.HB);
|
|
||||||
this.engine = new Engine(this.HB, text_types.parser);
|
|
||||||
this.connector = new Connector(this.engine, this.HB, text_types.execution_listener);
|
|
||||||
first_word = new text_types.types.Word(void 0);
|
|
||||||
this.HB.addOperation(first_word).execute();
|
|
||||||
this.root_element = first_word;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextYatta.prototype.getRootElement = function() {
|
|
||||||
return this.root_element;
|
|
||||||
};
|
|
||||||
|
|
||||||
TextYatta.prototype.getEngine = function() {
|
|
||||||
return this.engine;
|
|
||||||
};
|
|
||||||
|
|
||||||
TextYatta.prototype.getConnector = function() {
|
|
||||||
return this.connector;
|
|
||||||
};
|
|
||||||
|
|
||||||
TextYatta.prototype.getHistoryBuffer = function() {
|
|
||||||
return this.HB;
|
|
||||||
};
|
|
||||||
|
|
||||||
TextYatta.prototype.getUserId = function() {
|
|
||||||
return this.HB.getUserId();
|
|
||||||
};
|
|
||||||
|
|
||||||
TextYatta.prototype.val = function() {
|
|
||||||
return this.root_element.val();
|
|
||||||
};
|
|
||||||
|
|
||||||
TextYatta.prototype.insertText = function(pos, content) {
|
|
||||||
return this.root_element.insertText(pos, content);
|
|
||||||
};
|
|
||||||
|
|
||||||
TextYatta.prototype.deleteText = function(pos, length) {
|
|
||||||
return this.root_element.deleteText(pos, length);
|
|
||||||
};
|
|
||||||
|
|
||||||
TextYatta.prototype.replaceText = function(text) {
|
|
||||||
return this.root_element.replaceText(text);
|
|
||||||
};
|
|
||||||
|
|
||||||
return TextYatta;
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
module.exports = TextYatta;
|
|
||||||
|
|
||||||
//# sourceMappingURL=TextYatta.js.map
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"file": "TextYatta.js",
|
|
||||||
"sourceRoot": "../../../lib/Frameworks/",
|
|
||||||
"sources": [
|
|
||||||
"TextYatta.coffee"
|
|
||||||
],
|
|
||||||
"names": [],
|
|
||||||
"mappings": "AACA,IAAA,0DAAA;;AAAA,wBAAA,GAA2B,OAAA,CAAQ,2BAAR,CAA3B,CAAA;;AAAA,aACA,GAAgB,OAAA,CAAQ,yBAAR,CADhB,CAAA;;AAAA,MAEA,GAAS,OAAA,CAAQ,kBAAR,CAFT,CAAA;;AAAA;AAae,EAAA,mBAAC,OAAD,EAAU,SAAV,GAAA;AACX,QAAA,sBAAA;AAAA,IAAA,IAAC,CAAA,EAAD,GAAU,IAAA,aAAA,CAAc,OAAd,CAAV,CAAA;AAAA,IACA,UAAA,GAAa,wBAAA,CAAyB,IAAC,CAAA,EAA1B,CADb,CAAA;AAAA,IAEA,IAAC,CAAA,MAAD,GAAc,IAAA,MAAA,CAAO,IAAC,CAAA,EAAR,EAAY,UAAU,CAAC,MAAvB,CAFd,CAAA;AAAA,IAGA,IAAC,CAAA,SAAD,GAAiB,IAAA,SAAA,CAAU,IAAC,CAAA,MAAX,EAAmB,IAAC,CAAA,EAApB,EAAwB,UAAU,CAAC,kBAAnC,CAHjB,CAAA;AAAA,IAKA,UAAA,GAAiB,IAAA,UAAU,CAAC,KAAK,CAAC,IAAjB,CAAsB,MAAtB,CALjB,CAAA;AAAA,IAMA,IAAC,CAAA,EAAE,CAAC,YAAJ,CAAiB,UAAjB,CAA4B,CAAC,OAA7B,CAAA,CANA,CAAA;AAAA,IAOA,IAAC,CAAA,YAAD,GAAgB,UAPhB,CADW;EAAA,CAAb;;AAAA,sBAaA,cAAA,GAAgB,SAAA,GAAA;WACd,IAAC,CAAA,aADa;EAAA,CAbhB,CAAA;;AAAA,sBAmBA,SAAA,GAAW,SAAA,GAAA;WACT,IAAC,CAAA,OADQ;EAAA,CAnBX,CAAA;;AAAA,sBAyBA,YAAA,GAAc,SAAA,GAAA;WACZ,IAAC,CAAA,UADW;EAAA,CAzBd,CAAA;;AAAA,sBA+BA,gBAAA,GAAkB,SAAA,GAAA;WAChB,IAAC,CAAA,GADe;EAAA,CA/BlB,CAAA;;AAAA,sBAuCA,SAAA,GAAW,SAAA,GAAA;WACT,IAAC,CAAA,EAAE,CAAC,SAAJ,CAAA,EADS;EAAA,CAvCX,CAAA;;AAAA,sBA6CA,GAAA,GAAK,SAAA,GAAA;WACH,IAAC,CAAA,YAAY,CAAC,GAAd,CAAA,EADG;EAAA,CA7CL,CAAA;;AAAA,sBAmDA,UAAA,GAAY,SAAC,GAAD,EAAM,OAAN,GAAA;WACV,IAAC,CAAA,YAAY,CAAC,UAAd,CAAyB,GAAzB,EAA8B,OAA9B,EADU;EAAA,CAnDZ,CAAA;;AAAA,sBAyDA,UAAA,GAAY,SAAC,GAAD,EAAM,MAAN,GAAA;WACV,IAAC,CAAA,YAAY,CAAC,UAAd,CAAyB,GAAzB,EAA8B,MAA9B,EADU;EAAA,CAzDZ,CAAA;;AAAA,sBA+DA,WAAA,GAAa,SAAC,IAAD,GAAA;WACX,IAAC,CAAA,YAAY,CAAC,WAAd,CAA0B,IAA1B,EADW;EAAA,CA/Db,CAAA;;mBAAA;;IAbF,CAAA;;AAAA,MAgFM,CAAC,OAAP,GAAiB,SAhFjB,CAAA"
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
var HistoryBuffer;
|
|
||||||
|
|
||||||
HistoryBuffer = (function() {
|
|
||||||
function HistoryBuffer(user_id) {
|
|
||||||
this.user_id = user_id;
|
|
||||||
this.operation_counter = {};
|
|
||||||
this.buffer = {};
|
|
||||||
this.change_listeners = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
HistoryBuffer.prototype.getUserId = function() {
|
|
||||||
return this.user_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
HistoryBuffer.prototype.getReservedUniqueIdentifier = function() {
|
|
||||||
return {
|
|
||||||
creator: '_',
|
|
||||||
op_number: '_'
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
HistoryBuffer.prototype.getOperationCounter = function() {
|
|
||||||
var ctn, res, user, _ref;
|
|
||||||
res = {};
|
|
||||||
_ref = this.operation_counter;
|
|
||||||
for (user in _ref) {
|
|
||||||
ctn = _ref[user];
|
|
||||||
res[user] = ctn;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
HistoryBuffer.prototype._encode = function(state_vector) {
|
|
||||||
var json, o, o_json, o_next, o_number, o_prev, u_name, unknown, user, _ref;
|
|
||||||
if (state_vector == null) {
|
|
||||||
state_vector = {};
|
|
||||||
}
|
|
||||||
json = [];
|
|
||||||
unknown = function(user, o_number) {
|
|
||||||
if ((user == null) || (o_number == null)) {
|
|
||||||
throw new Error("dah!");
|
|
||||||
}
|
|
||||||
return (state_vector[user] == null) || state_vector[user] <= o_number;
|
|
||||||
};
|
|
||||||
_ref = this.buffer;
|
|
||||||
for (u_name in _ref) {
|
|
||||||
user = _ref[u_name];
|
|
||||||
for (o_number in user) {
|
|
||||||
o = user[o_number];
|
|
||||||
if (!isNaN(parseInt(o_number)) && unknown(u_name, o_number)) {
|
|
||||||
o_json = o._encode();
|
|
||||||
if (o.next_cl != null) {
|
|
||||||
o_next = o.next_cl;
|
|
||||||
while ((o_next.next_cl != null) && unknown(o_next.creator, o_next.op_number)) {
|
|
||||||
o_next = o_next.next_cl;
|
|
||||||
}
|
|
||||||
o_json.next = o_next.getUid();
|
|
||||||
} else if (o.prev_cl != null) {
|
|
||||||
o_prev = o.prev_cl;
|
|
||||||
while ((o_prev.prev_cl != null) && unknown(o_next.creator, o_next.op_number)) {
|
|
||||||
o_prev = o_prev.prev_cl;
|
|
||||||
}
|
|
||||||
o_json.prev = o_prev.getUid();
|
|
||||||
}
|
|
||||||
json.push(o_json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
};
|
|
||||||
|
|
||||||
HistoryBuffer.prototype.getNextOperationIdentifier = function(user_id) {
|
|
||||||
var uid;
|
|
||||||
if (user_id == null) {
|
|
||||||
user_id = this.user_id;
|
|
||||||
}
|
|
||||||
if (this.operation_counter[user_id] == null) {
|
|
||||||
this.operation_counter[user_id] = 0;
|
|
||||||
}
|
|
||||||
uid = {
|
|
||||||
'creator': user_id,
|
|
||||||
'op_number': this.operation_counter[user_id]
|
|
||||||
};
|
|
||||||
this.operation_counter[user_id]++;
|
|
||||||
return uid;
|
|
||||||
};
|
|
||||||
|
|
||||||
HistoryBuffer.prototype.getOperation = function(uid) {
|
|
||||||
var _ref;
|
|
||||||
if (uid instanceof Object) {
|
|
||||||
return (_ref = this.buffer[uid.creator]) != null ? _ref[uid.op_number] : void 0;
|
|
||||||
} else if (uid == null) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new Error("This type of uid is not defined!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
HistoryBuffer.prototype.addOperation = function(o) {
|
|
||||||
if (this.buffer[o.creator] == null) {
|
|
||||||
this.buffer[o.creator] = {};
|
|
||||||
}
|
|
||||||
if (this.buffer[o.creator][o.op_number] != null) {
|
|
||||||
throw new Error("You must not overwrite operations!");
|
|
||||||
}
|
|
||||||
this.buffer[o.creator][o.op_number] = o;
|
|
||||||
return o;
|
|
||||||
};
|
|
||||||
|
|
||||||
HistoryBuffer.prototype.addToCounter = function(o) {
|
|
||||||
if (this.operation_counter[o.creator] == null) {
|
|
||||||
this.operation_counter[o.creator] = 0;
|
|
||||||
}
|
|
||||||
if (typeof o.op_number === 'number' && o.creator !== this.getUserId()) {
|
|
||||||
return this.operation_counter[o.creator]++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return HistoryBuffer;
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
module.exports = HistoryBuffer;
|
|
||||||
|
|
||||||
//# sourceMappingURL=HistoryBuffer.js.map
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"file": "HistoryBuffer.js",
|
|
||||||
"sourceRoot": "../../lib/",
|
|
||||||
"sources": [
|
|
||||||
"HistoryBuffer.coffee"
|
|
||||||
],
|
|
||||||
"names": [],
|
|
||||||
"mappings": "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"
|
|
||||||
}
|
|
||||||
@@ -1,330 +0,0 @@
|
|||||||
var __hasProp = {}.hasOwnProperty,
|
|
||||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
||||||
|
|
||||||
module.exports = function(HB) {
|
|
||||||
var Delete, Delimiter, ImmutableObject, Insert, Operation, execution_listener, parser;
|
|
||||||
parser = {};
|
|
||||||
execution_listener = [];
|
|
||||||
Operation = (function() {
|
|
||||||
function Operation(uid) {
|
|
||||||
if (uid == null) {
|
|
||||||
uid = HB.getNextOperationIdentifier();
|
|
||||||
}
|
|
||||||
this.creator = uid['creator'], this.op_number = uid['op_number'];
|
|
||||||
}
|
|
||||||
|
|
||||||
Operation.prototype.getUid = function() {
|
|
||||||
return {
|
|
||||||
'creator': this.creator,
|
|
||||||
'op_number': this.op_number
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
Operation.prototype.execute = function() {
|
|
||||||
var l, _i, _len;
|
|
||||||
this.is_executed = true;
|
|
||||||
for (_i = 0, _len = execution_listener.length; _i < _len; _i++) {
|
|
||||||
l = execution_listener[_i];
|
|
||||||
l(this._encode());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Operation.prototype.saveOperation = function(name, op) {
|
|
||||||
if ((op != null ? op.execute : void 0) != null) {
|
|
||||||
return this[name] = op;
|
|
||||||
} else if (op != null) {
|
|
||||||
if (this.unchecked == null) {
|
|
||||||
this.unchecked = {};
|
|
||||||
}
|
|
||||||
return this.unchecked[name] = op;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Operation.prototype.validateSavedOperations = function() {
|
|
||||||
var name, op, op_uid, success, uninstantiated, _ref;
|
|
||||||
uninstantiated = {};
|
|
||||||
success = this;
|
|
||||||
_ref = this.unchecked;
|
|
||||||
for (name in _ref) {
|
|
||||||
op_uid = _ref[name];
|
|
||||||
op = HB.getOperation(op_uid);
|
|
||||||
if (op) {
|
|
||||||
this[name] = op;
|
|
||||||
} else {
|
|
||||||
uninstantiated[name] = op_uid;
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete this.unchecked;
|
|
||||||
if (!success) {
|
|
||||||
this.unchecked = uninstantiated;
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
};
|
|
||||||
|
|
||||||
return Operation;
|
|
||||||
|
|
||||||
})();
|
|
||||||
Delete = (function(_super) {
|
|
||||||
__extends(Delete, _super);
|
|
||||||
|
|
||||||
function Delete(uid, deletes) {
|
|
||||||
this.saveOperation('deletes', deletes);
|
|
||||||
Delete.__super__.constructor.call(this, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
Delete.prototype._encode = function() {
|
|
||||||
return {
|
|
||||||
'type': "Delete",
|
|
||||||
'uid': this.getUid(),
|
|
||||||
'deletes': this.deletes.getUid()
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
Delete.prototype.execute = function() {
|
|
||||||
if (this.validateSavedOperations()) {
|
|
||||||
this.deletes.applyDelete(this);
|
|
||||||
Delete.__super__.execute.apply(this, arguments);
|
|
||||||
return this;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Delete;
|
|
||||||
|
|
||||||
})(Operation);
|
|
||||||
parser['Delete'] = function(o) {
|
|
||||||
var deletes_uid, uid;
|
|
||||||
uid = o['uid'], deletes_uid = o['deletes'];
|
|
||||||
return new Delete(uid, deletes_uid);
|
|
||||||
};
|
|
||||||
Insert = (function(_super) {
|
|
||||||
__extends(Insert, _super);
|
|
||||||
|
|
||||||
function Insert(uid, prev_cl, next_cl, origin) {
|
|
||||||
this.saveOperation('prev_cl', prev_cl);
|
|
||||||
this.saveOperation('next_cl', next_cl);
|
|
||||||
if (origin != null) {
|
|
||||||
this.saveOperation('origin', origin);
|
|
||||||
} else {
|
|
||||||
this.saveOperation('origin', prev_cl);
|
|
||||||
}
|
|
||||||
Insert.__super__.constructor.call(this, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
Insert.prototype.applyDelete = function(o) {
|
|
||||||
if (this.deleted_by == null) {
|
|
||||||
this.deleted_by = [];
|
|
||||||
}
|
|
||||||
return this.deleted_by.push(o);
|
|
||||||
};
|
|
||||||
|
|
||||||
Insert.prototype.isDeleted = function() {
|
|
||||||
var _ref;
|
|
||||||
return ((_ref = this.deleted_by) != null ? _ref.length : void 0) > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Insert.prototype.getDistanceToOrigin = function() {
|
|
||||||
var d, o;
|
|
||||||
d = 0;
|
|
||||||
o = this.prev_cl;
|
|
||||||
while (true) {
|
|
||||||
if (this.origin === o) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
d++;
|
|
||||||
if (this === this.prev_cl) {
|
|
||||||
throw new Error("this should not happen ;) ");
|
|
||||||
}
|
|
||||||
o = o.prev_cl;
|
|
||||||
}
|
|
||||||
return d;
|
|
||||||
};
|
|
||||||
|
|
||||||
Insert.prototype.update_sl = function() {
|
|
||||||
var o;
|
|
||||||
o = this.prev_cl;
|
|
||||||
({
|
|
||||||
update: function(dest_cl, dest_sl) {
|
|
||||||
var _results;
|
|
||||||
_results = [];
|
|
||||||
while (true) {
|
|
||||||
if (o.isDeleted()) {
|
|
||||||
_results.push(o = o[dest_cl]);
|
|
||||||
} else {
|
|
||||||
this[dest_sl] = o;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
update("prev_cl", "prev_sl");
|
|
||||||
return update("next_cl", "prev_sl");
|
|
||||||
};
|
|
||||||
|
|
||||||
Insert.prototype.execute = function() {
|
|
||||||
var distance_to_origin, i, o, _ref, _ref1;
|
|
||||||
if (this.is_executed != null) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
if (!this.validateSavedOperations()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) {
|
|
||||||
distance_to_origin = 0;
|
|
||||||
o = this.prev_cl.next_cl;
|
|
||||||
i = 0;
|
|
||||||
while (true) {
|
|
||||||
if (o == null) {
|
|
||||||
console.log(JSON.stringify(this.prev_cl.getUid()));
|
|
||||||
console.log(JSON.stringify(this.next_cl.getUid()));
|
|
||||||
}
|
|
||||||
if (o !== this.next_cl) {
|
|
||||||
if (o.getDistanceToOrigin() === i) {
|
|
||||||
if (o.creator < this.creator) {
|
|
||||||
this.prev_cl = o;
|
|
||||||
distance_to_origin = i + 1;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
} else if (o.getDistanceToOrigin() < i) {
|
|
||||||
if (i - distance_to_origin <= o.getDistanceToOrigin()) {
|
|
||||||
this.prev_cl = o;
|
|
||||||
distance_to_origin = i + 1;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
o = o.next_cl;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.next_cl = this.prev_cl.next_cl;
|
|
||||||
this.prev_cl.next_cl = this;
|
|
||||||
this.next_cl.prev_cl = this;
|
|
||||||
}
|
|
||||||
Insert.__super__.execute.apply(this, arguments);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Insert;
|
|
||||||
|
|
||||||
})(Operation);
|
|
||||||
ImmutableObject = (function(_super) {
|
|
||||||
__extends(ImmutableObject, _super);
|
|
||||||
|
|
||||||
function ImmutableObject(uid, content, prev, next, origin) {
|
|
||||||
this.content = content;
|
|
||||||
ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmutableObject.prototype.val = function() {
|
|
||||||
return this.content;
|
|
||||||
};
|
|
||||||
|
|
||||||
ImmutableObject.prototype._encode = function() {
|
|
||||||
var json;
|
|
||||||
json = {
|
|
||||||
'type': "ImmutableObject",
|
|
||||||
'uid': this.getUid(),
|
|
||||||
'content': this.content
|
|
||||||
};
|
|
||||||
if (this.prev_cl != null) {
|
|
||||||
json['prev'] = this.prev_cl.getUid();
|
|
||||||
}
|
|
||||||
if (this.next_cl != null) {
|
|
||||||
json['next'] = this.next_cl.getUid();
|
|
||||||
}
|
|
||||||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
|
||||||
json["origin"] = this.origin.getUid();
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
};
|
|
||||||
|
|
||||||
return ImmutableObject;
|
|
||||||
|
|
||||||
})(Insert);
|
|
||||||
parser['ImmutableObject'] = function(json) {
|
|
||||||
var content, next, origin, prev, uid;
|
|
||||||
uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin'];
|
|
||||||
return new ImmutableObject(uid, content, prev, next, origin);
|
|
||||||
};
|
|
||||||
Delimiter = (function(_super) {
|
|
||||||
__extends(Delimiter, _super);
|
|
||||||
|
|
||||||
function Delimiter(uid, prev_cl, next_cl, origin) {
|
|
||||||
this.saveOperation('prev_cl', prev_cl);
|
|
||||||
this.saveOperation('next_cl', next_cl);
|
|
||||||
this.saveOperation('origin', prev_cl);
|
|
||||||
Delimiter.__super__.constructor.call(this, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
Delimiter.prototype.isDeleted = function() {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
Delimiter.prototype.execute = function() {
|
|
||||||
var _ref, _ref1;
|
|
||||||
if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) {
|
|
||||||
return Delimiter.__super__.execute.apply(this, arguments);
|
|
||||||
} else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) {
|
|
||||||
if (this.validateSavedOperations()) {
|
|
||||||
if (this.prev_cl.next_cl != null) {
|
|
||||||
throw new Error("Probably duplicated operations");
|
|
||||||
}
|
|
||||||
this.prev_cl.next_cl = this;
|
|
||||||
delete this.prev_cl.unchecked.next_cl;
|
|
||||||
return Delimiter.__super__.execute.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) {
|
|
||||||
delete this.prev_cl.unchecked.next_cl;
|
|
||||||
return this.prev_cl.next_cl = this;
|
|
||||||
} else if ((this.prev_cl != null) || (this.next_cl != null)) {
|
|
||||||
return Delimiter.__super__.execute.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
throw new Error("Delimiter is unsufficient defined!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Delimiter.prototype._encode = function() {
|
|
||||||
var _ref, _ref1;
|
|
||||||
return {
|
|
||||||
'type': "Delimiter",
|
|
||||||
'uid': this.getUid(),
|
|
||||||
'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0,
|
|
||||||
'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return Delimiter;
|
|
||||||
|
|
||||||
})(Operation);
|
|
||||||
parser['Delimiter'] = function(json) {
|
|
||||||
var next, prev, uid;
|
|
||||||
uid = json['uid'], prev = json['prev'], next = json['next'];
|
|
||||||
return new Delimiter(uid, prev, next);
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
'types': {
|
|
||||||
'Delete': Delete,
|
|
||||||
'Insert': Insert,
|
|
||||||
'Delimiter': Delimiter,
|
|
||||||
'Operation': Operation,
|
|
||||||
'ImmutableObject': ImmutableObject
|
|
||||||
},
|
|
||||||
'parser': parser,
|
|
||||||
'execution_listener': execution_listener
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
//# sourceMappingURL=BasicTypes.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,168 +0,0 @@
|
|||||||
var text_types_uninitialized,
|
|
||||||
__hasProp = {}.hasOwnProperty,
|
|
||||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
||||||
|
|
||||||
text_types_uninitialized = require("./TextTypes.coffee");
|
|
||||||
|
|
||||||
module.exports = function(HB) {
|
|
||||||
var JsonType, createJsonWrapper, parser, text_types, types;
|
|
||||||
text_types = text_types_uninitialized(HB);
|
|
||||||
types = text_types.types;
|
|
||||||
parser = text_types.parser;
|
|
||||||
createJsonWrapper = function(_jsonType) {
|
|
||||||
var JsonWrapper;
|
|
||||||
JsonWrapper = (function() {
|
|
||||||
function JsonWrapper(jsonType) {
|
|
||||||
var name, obj, _fn, _ref;
|
|
||||||
_ref = jsonType.map;
|
|
||||||
_fn = function(name, obj) {
|
|
||||||
return Object.defineProperty(JsonWrapper.prototype, name, {
|
|
||||||
get: function() {
|
|
||||||
var x;
|
|
||||||
x = obj.val();
|
|
||||||
if (x instanceof JsonType) {
|
|
||||||
return createJsonWrapper(x);
|
|
||||||
} else if (x instanceof types.ImmutableObject) {
|
|
||||||
return x.val();
|
|
||||||
} else {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
set: function(o) {
|
|
||||||
var o_name, o_obj, overwrite, _results;
|
|
||||||
if (o.constructor === {}.constructor) {
|
|
||||||
overwrite = jsonType.val(name);
|
|
||||||
_results = [];
|
|
||||||
for (o_name in o) {
|
|
||||||
o_obj = o[o_name];
|
|
||||||
_results.push(overwrite.val(o_name, o_obj, 'immutable'));
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
} else {
|
|
||||||
return jsonType.val(name, o, 'immutable');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enumerable: true,
|
|
||||||
configurable: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
for (name in _ref) {
|
|
||||||
obj = _ref[name];
|
|
||||||
_fn(name, obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return JsonWrapper;
|
|
||||||
|
|
||||||
})();
|
|
||||||
return new JsonWrapper(_jsonType);
|
|
||||||
};
|
|
||||||
JsonType = (function(_super) {
|
|
||||||
__extends(JsonType, _super);
|
|
||||||
|
|
||||||
function JsonType(uid, initial_value, mutable) {
|
|
||||||
var name, o;
|
|
||||||
JsonType.__super__.constructor.call(this, uid);
|
|
||||||
if (initial_value != null) {
|
|
||||||
if (typeof initial_value !== "object") {
|
|
||||||
throw new Error("The initial value of JsonTypes must be of type Object! (current type: " + (typeof initial_value) + ")");
|
|
||||||
}
|
|
||||||
for (name in initial_value) {
|
|
||||||
o = initial_value[name];
|
|
||||||
this.val(name, o, mutable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonType.prototype.mutable_default = true;
|
|
||||||
|
|
||||||
JsonType.prototype.setMutableDefault = function(mutable) {
|
|
||||||
if (mutable === true || mutable === 'mutable') {
|
|
||||||
JsonType.prototype.mutable_default = true;
|
|
||||||
} else if (mutable === false || mutable === 'immutable') {
|
|
||||||
JsonType.prototype.mutable_default = false;
|
|
||||||
} else {
|
|
||||||
throw new Error('Set mutable either "mutable" or "immutable"!');
|
|
||||||
}
|
|
||||||
return 'OK';
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonType.prototype.val = function(name, content, mutable) {
|
|
||||||
var json, o, o_name, obj, word;
|
|
||||||
if (typeof name === 'object') {
|
|
||||||
for (o_name in name) {
|
|
||||||
o = name[o_name];
|
|
||||||
this.val(o_name, o, content);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
} else if ((name != null) && (content != null)) {
|
|
||||||
if (mutable != null) {
|
|
||||||
if (mutable === true || mutable === 'mutable') {
|
|
||||||
mutable = true;
|
|
||||||
} else {
|
|
||||||
mutable = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mutable = this.mutable_default;
|
|
||||||
}
|
|
||||||
if (typeof content === 'function') {
|
|
||||||
return this;
|
|
||||||
} else if (((!mutable) || typeof content === 'number') && content.constructor !== Object) {
|
|
||||||
obj = HB.addOperation(new types.ImmutableObject(void 0, content)).execute();
|
|
||||||
return JsonType.__super__.val.call(this, name, obj);
|
|
||||||
} else {
|
|
||||||
if (typeof content === 'string') {
|
|
||||||
word = HB.addOperation(new types.Word(void 0)).execute();
|
|
||||||
word.insertText(0, content);
|
|
||||||
return JsonType.__super__.val.call(this, name, word);
|
|
||||||
} else if (content.constructor === Object) {
|
|
||||||
json = HB.addOperation(new JsonType(void 0, content, mutable)).execute();
|
|
||||||
return JsonType.__super__.val.call(this, name, json);
|
|
||||||
} else {
|
|
||||||
throw new Error("You must not set " + (typeof content) + "-types in collaborative Json-objects!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return JsonType.__super__.val.call(this, name, content);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperty(JsonType.prototype, 'value', {
|
|
||||||
get: function() {
|
|
||||||
return createJsonWrapper(this);
|
|
||||||
},
|
|
||||||
set: function(o) {
|
|
||||||
var o_name, o_obj, _results;
|
|
||||||
if (o.constructor === {}.constructor) {
|
|
||||||
_results = [];
|
|
||||||
for (o_name in o) {
|
|
||||||
o_obj = o[o_name];
|
|
||||||
_results.push(this.val(o_name, o_obj, 'immutable'));
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
} else {
|
|
||||||
throw new Error("You must only set Object values!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
JsonType.prototype._encode = function() {
|
|
||||||
return {
|
|
||||||
'type': "JsonType",
|
|
||||||
'uid': this.getUid()
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return JsonType;
|
|
||||||
|
|
||||||
})(types.MapManager);
|
|
||||||
parser['JsonType'] = function(json) {
|
|
||||||
var uid;
|
|
||||||
uid = json['uid'];
|
|
||||||
return new JsonType(uid);
|
|
||||||
};
|
|
||||||
types['JsonType'] = JsonType;
|
|
||||||
return text_types;
|
|
||||||
};
|
|
||||||
|
|
||||||
//# sourceMappingURL=JsonTypes.js.map
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"file": "JsonTypes.js",
|
|
||||||
"sourceRoot": "../../../lib/Types/",
|
|
||||||
"sources": [
|
|
||||||
"JsonTypes.coffee"
|
|
||||||
],
|
|
||||||
"names": [],
|
|
||||||
"mappings": "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"
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
var basic_types_uninitialized,
|
|
||||||
__hasProp = {}.hasOwnProperty,
|
|
||||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
||||||
|
|
||||||
basic_types_uninitialized = require("./BasicTypes.coffee");
|
|
||||||
|
|
||||||
module.exports = function(HB) {
|
|
||||||
var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types;
|
|
||||||
basic_types = basic_types_uninitialized(HB);
|
|
||||||
types = basic_types.types;
|
|
||||||
parser = basic_types.parser;
|
|
||||||
MapManager = (function(_super) {
|
|
||||||
__extends(MapManager, _super);
|
|
||||||
|
|
||||||
function MapManager(uid) {
|
|
||||||
this.map = {};
|
|
||||||
MapManager.__super__.constructor.call(this, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
MapManager.prototype.val = function(name, content) {
|
|
||||||
var o, obj, result, _ref, _ref1;
|
|
||||||
if (content != null) {
|
|
||||||
if (this.map[name] == null) {
|
|
||||||
HB.addOperation(new AddName(void 0, this, name)).execute();
|
|
||||||
}
|
|
||||||
this.map[name].replace(content);
|
|
||||||
return this;
|
|
||||||
} else if (name != null) {
|
|
||||||
obj = (_ref = this.map[name]) != null ? _ref.val() : void 0;
|
|
||||||
if (obj instanceof types.ImmutableObject) {
|
|
||||||
return obj.val();
|
|
||||||
} else {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result = {};
|
|
||||||
_ref1 = this.map;
|
|
||||||
for (name in _ref1) {
|
|
||||||
o = _ref1[name];
|
|
||||||
obj = o.val();
|
|
||||||
if (obj instanceof types.ImmutableObject || obj instanceof MapManager) {
|
|
||||||
obj = obj.val();
|
|
||||||
}
|
|
||||||
result[name] = obj;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return MapManager;
|
|
||||||
|
|
||||||
})(types.Operation);
|
|
||||||
AddName = (function(_super) {
|
|
||||||
__extends(AddName, _super);
|
|
||||||
|
|
||||||
function AddName(uid, map_manager, name) {
|
|
||||||
this.name = name;
|
|
||||||
this.saveOperation('map_manager', map_manager);
|
|
||||||
AddName.__super__.constructor.call(this, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddName.prototype.execute = function() {
|
|
||||||
var beg, end, uid_beg, uid_end, uid_r;
|
|
||||||
if (!this.validateSavedOperations()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
uid_r = this.map_manager.getUid();
|
|
||||||
uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name;
|
|
||||||
if (HB.getOperation(uid_r) == null) {
|
|
||||||
uid_beg = this.map_manager.getUid();
|
|
||||||
uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning";
|
|
||||||
uid_end = this.map_manager.getUid();
|
|
||||||
uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end";
|
|
||||||
beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute();
|
|
||||||
end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute();
|
|
||||||
this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute();
|
|
||||||
}
|
|
||||||
return AddName.__super__.execute.apply(this, arguments);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
AddName.prototype._encode = function() {
|
|
||||||
return {
|
|
||||||
'type': "AddName",
|
|
||||||
'uid': this.getUid(),
|
|
||||||
'map_manager': this.map_manager.getUid(),
|
|
||||||
'name': this.name
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return AddName;
|
|
||||||
|
|
||||||
})(types.Operation);
|
|
||||||
parser['AddName'] = function(json) {
|
|
||||||
var map_manager, name, uid;
|
|
||||||
map_manager = json['map_manager'], uid = json['uid'], name = json['name'];
|
|
||||||
return new AddName(uid, map_manager, name);
|
|
||||||
};
|
|
||||||
ListManager = (function(_super) {
|
|
||||||
__extends(ListManager, _super);
|
|
||||||
|
|
||||||
function ListManager(uid, beginning, end, prev, next, origin) {
|
|
||||||
if ((beginning != null) && (end != null)) {
|
|
||||||
this.saveOperation('beginning', beginning);
|
|
||||||
this.saveOperation('end', end);
|
|
||||||
} else {
|
|
||||||
this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0));
|
|
||||||
this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0));
|
|
||||||
this.beginning.next_cl = this.end;
|
|
||||||
this.beginning.execute();
|
|
||||||
this.end.execute();
|
|
||||||
}
|
|
||||||
ListManager.__super__.constructor.call(this, uid, prev, next, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
ListManager.prototype.getLastOperation = function() {
|
|
||||||
return this.end.prev_cl;
|
|
||||||
};
|
|
||||||
|
|
||||||
ListManager.prototype.getFirstOperation = function() {
|
|
||||||
return this.beginning.next_cl;
|
|
||||||
};
|
|
||||||
|
|
||||||
ListManager.prototype.toArray = function() {
|
|
||||||
var o, result;
|
|
||||||
o = this.beginning.next_cl;
|
|
||||||
result = [];
|
|
||||||
while (o !== this.end) {
|
|
||||||
result.push(o);
|
|
||||||
o = o.next_cl;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
ListManager.prototype.getOperationByPosition = function(position) {
|
|
||||||
var o;
|
|
||||||
o = this.beginning.next_cl;
|
|
||||||
if (position > 0) {
|
|
||||||
while (true) {
|
|
||||||
o = o.next_cl;
|
|
||||||
if (!o.isDeleted()) {
|
|
||||||
position -= 1;
|
|
||||||
}
|
|
||||||
if (position === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (o instanceof types.Delimiter) {
|
|
||||||
throw new Error("position parameter exceeded the length of the document!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
};
|
|
||||||
|
|
||||||
return ListManager;
|
|
||||||
|
|
||||||
})(types.Insert);
|
|
||||||
ReplaceManager = (function(_super) {
|
|
||||||
__extends(ReplaceManager, _super);
|
|
||||||
|
|
||||||
function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) {
|
|
||||||
ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin);
|
|
||||||
if (initial_content != null) {
|
|
||||||
this.replace(initial_content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReplaceManager.prototype.replace = function(content) {
|
|
||||||
var o, op;
|
|
||||||
o = this.getLastOperation();
|
|
||||||
op = new Replaceable(content, this, void 0, o, o.next_cl);
|
|
||||||
return HB.addOperation(op).execute();
|
|
||||||
};
|
|
||||||
|
|
||||||
ReplaceManager.prototype.val = function() {
|
|
||||||
var o;
|
|
||||||
o = this.getLastOperation();
|
|
||||||
if (o instanceof types.Delimiter) {
|
|
||||||
throw new Error("dtrn");
|
|
||||||
}
|
|
||||||
return o.val();
|
|
||||||
};
|
|
||||||
|
|
||||||
ReplaceManager.prototype._encode = function() {
|
|
||||||
var json;
|
|
||||||
json = {
|
|
||||||
'type': "ReplaceManager",
|
|
||||||
'uid': this.getUid(),
|
|
||||||
'beginning': this.beginning.getUid(),
|
|
||||||
'end': this.end.getUid()
|
|
||||||
};
|
|
||||||
if ((this.prev_cl != null) && (this.next_cl != null)) {
|
|
||||||
json['prev'] = this.prev_cl.getUid();
|
|
||||||
json['next'] = this.next_cl.getUid();
|
|
||||||
}
|
|
||||||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
|
||||||
json["origin"] = this.origin.getUid();
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
};
|
|
||||||
|
|
||||||
return ReplaceManager;
|
|
||||||
|
|
||||||
})(ListManager);
|
|
||||||
parser["ReplaceManager"] = function(json) {
|
|
||||||
var beginning, content, end, next, origin, prev, uid;
|
|
||||||
content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end'];
|
|
||||||
return new ReplaceManager(content, uid, beginning, end, prev, next, origin);
|
|
||||||
};
|
|
||||||
Replaceable = (function(_super) {
|
|
||||||
__extends(Replaceable, _super);
|
|
||||||
|
|
||||||
function Replaceable(content, parent, uid, prev, next, origin) {
|
|
||||||
this.saveOperation('content', content);
|
|
||||||
this.saveOperation('parent', parent);
|
|
||||||
if (!((prev != null) && (next != null) && (content != null))) {
|
|
||||||
throw new Error("You must define content, prev, and next for Replaceable-types!");
|
|
||||||
}
|
|
||||||
Replaceable.__super__.constructor.call(this, uid, prev, next, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
Replaceable.prototype.val = function() {
|
|
||||||
return this.content;
|
|
||||||
};
|
|
||||||
|
|
||||||
Replaceable.prototype.replace = function(content) {
|
|
||||||
return this.parent.replace(content);
|
|
||||||
};
|
|
||||||
|
|
||||||
Replaceable.prototype.execute = function() {
|
|
||||||
var _base;
|
|
||||||
if (!this.validateSavedOperations()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
if (typeof (_base = this.content).setReplaceManager === "function") {
|
|
||||||
_base.setReplaceManager(this.parent);
|
|
||||||
}
|
|
||||||
Replaceable.__super__.execute.apply(this, arguments);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Replaceable.prototype._encode = function() {
|
|
||||||
var json;
|
|
||||||
json = {
|
|
||||||
'type': "Replaceable",
|
|
||||||
'content': this.content.getUid(),
|
|
||||||
'ReplaceManager': this.parent.getUid(),
|
|
||||||
'prev': this.prev_cl.getUid(),
|
|
||||||
'next': this.next_cl.getUid(),
|
|
||||||
'uid': this.getUid()
|
|
||||||
};
|
|
||||||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
|
||||||
json["origin"] = this.origin.getUid();
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
};
|
|
||||||
|
|
||||||
return Replaceable;
|
|
||||||
|
|
||||||
})(types.Insert);
|
|
||||||
parser["Replaceable"] = function(json) {
|
|
||||||
var content, next, origin, parent, prev, uid;
|
|
||||||
content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'];
|
|
||||||
return new Replaceable(content, parent, uid, prev, next, origin);
|
|
||||||
};
|
|
||||||
types['ListManager'] = ListManager;
|
|
||||||
types['MapManager'] = MapManager;
|
|
||||||
types['ReplaceManager'] = ReplaceManager;
|
|
||||||
types['Replaceable'] = Replaceable;
|
|
||||||
return basic_types;
|
|
||||||
};
|
|
||||||
|
|
||||||
//# sourceMappingURL=StructuredTypes.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,179 +0,0 @@
|
|||||||
var structured_types_uninitialized,
|
|
||||||
__hasProp = {}.hasOwnProperty,
|
|
||||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
||||||
|
|
||||||
structured_types_uninitialized = require("./StructuredTypes.coffee");
|
|
||||||
|
|
||||||
module.exports = function(HB) {
|
|
||||||
var TextDelete, TextInsert, Word, parser, structured_types, types;
|
|
||||||
structured_types = structured_types_uninitialized(HB);
|
|
||||||
types = structured_types.types;
|
|
||||||
parser = structured_types.parser;
|
|
||||||
TextDelete = (function(_super) {
|
|
||||||
__extends(TextDelete, _super);
|
|
||||||
|
|
||||||
function TextDelete() {
|
|
||||||
return TextDelete.__super__.constructor.apply(this, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TextDelete;
|
|
||||||
|
|
||||||
})(types.Delete);
|
|
||||||
parser["TextDelete"] = parser["Delete"];
|
|
||||||
TextInsert = (function(_super) {
|
|
||||||
__extends(TextInsert, _super);
|
|
||||||
|
|
||||||
function TextInsert(content, uid, prev, next, origin) {
|
|
||||||
this.content = content;
|
|
||||||
if (!((prev != null) && (next != null))) {
|
|
||||||
throw new Error("You must define prev, and next for TextInsert-types!");
|
|
||||||
}
|
|
||||||
TextInsert.__super__.constructor.call(this, uid, prev, next, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextInsert.prototype.getLength = function() {
|
|
||||||
if (this.isDeleted()) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return this.content.length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TextInsert.prototype.val = function(current_position) {
|
|
||||||
if (this.isDeleted()) {
|
|
||||||
return "";
|
|
||||||
} else {
|
|
||||||
return this.content;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TextInsert.prototype._encode = function() {
|
|
||||||
var json;
|
|
||||||
json = {
|
|
||||||
'type': "TextInsert",
|
|
||||||
'content': this.content,
|
|
||||||
'uid': this.getUid(),
|
|
||||||
'prev': this.prev_cl.getUid(),
|
|
||||||
'next': this.next_cl.getUid()
|
|
||||||
};
|
|
||||||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
|
||||||
json["origin"] = this.origin.getUid();
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
};
|
|
||||||
|
|
||||||
return TextInsert;
|
|
||||||
|
|
||||||
})(types.Insert);
|
|
||||||
parser["TextInsert"] = function(json) {
|
|
||||||
var content, next, origin, prev, uid;
|
|
||||||
content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'];
|
|
||||||
return new TextInsert(content, uid, prev, next, origin);
|
|
||||||
};
|
|
||||||
Word = (function(_super) {
|
|
||||||
__extends(Word, _super);
|
|
||||||
|
|
||||||
function Word(uid, beginning, end, prev, next, origin) {
|
|
||||||
Word.__super__.constructor.call(this, uid, beginning, end, prev, next, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
Word.prototype.insertText = function(position, content) {
|
|
||||||
var c, o, op, _i, _len, _results;
|
|
||||||
o = this.getOperationByPosition(position);
|
|
||||||
_results = [];
|
|
||||||
for (_i = 0, _len = content.length; _i < _len; _i++) {
|
|
||||||
c = content[_i];
|
|
||||||
op = new TextInsert(c, void 0, o.prev_cl, o);
|
|
||||||
_results.push(HB.addOperation(op).execute());
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
};
|
|
||||||
|
|
||||||
Word.prototype.deleteText = function(position, length) {
|
|
||||||
var d, i, o, _i, _results;
|
|
||||||
o = this.getOperationByPosition(position);
|
|
||||||
_results = [];
|
|
||||||
for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {
|
|
||||||
d = HB.addOperation(new TextDelete(void 0, o)).execute();
|
|
||||||
o = o.next_cl;
|
|
||||||
while (o.isDeleted()) {
|
|
||||||
if (o instanceof types.Delimiter) {
|
|
||||||
throw new Error("You can't delete more than there is..");
|
|
||||||
}
|
|
||||||
o = o.next_cl;
|
|
||||||
}
|
|
||||||
_results.push(d._encode());
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
};
|
|
||||||
|
|
||||||
Word.prototype.replaceText = function(text) {
|
|
||||||
var word;
|
|
||||||
if (this.replace_manager != null) {
|
|
||||||
word = HB.addOperation(new Word(void 0)).execute();
|
|
||||||
word.insertText(0, text);
|
|
||||||
return this.replace_manager.replace(word);
|
|
||||||
} else {
|
|
||||||
throw new Error("This type is currently not maintained by a ReplaceManager!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Word.prototype.val = function() {
|
|
||||||
var c, o;
|
|
||||||
c = (function() {
|
|
||||||
var _i, _len, _ref, _results;
|
|
||||||
_ref = this.toArray();
|
|
||||||
_results = [];
|
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
||||||
o = _ref[_i];
|
|
||||||
if (o.val != null) {
|
|
||||||
_results.push(o.val());
|
|
||||||
} else {
|
|
||||||
_results.push("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _results;
|
|
||||||
}).call(this);
|
|
||||||
return c.join('');
|
|
||||||
};
|
|
||||||
|
|
||||||
Word.prototype.setReplaceManager = function(op) {
|
|
||||||
this.saveOperation('replace_manager', op);
|
|
||||||
return this.validateSavedOperations;
|
|
||||||
};
|
|
||||||
|
|
||||||
Word.prototype._encode = function() {
|
|
||||||
var json;
|
|
||||||
json = {
|
|
||||||
'type': "Word",
|
|
||||||
'uid': this.getUid(),
|
|
||||||
'beginning': this.beginning.getUid(),
|
|
||||||
'end': this.end.getUid()
|
|
||||||
};
|
|
||||||
if (this.prev_cl != null) {
|
|
||||||
json['prev'] = this.prev_cl.getUid();
|
|
||||||
}
|
|
||||||
if (this.next_cl != null) {
|
|
||||||
json['next'] = this.next_cl.getUid();
|
|
||||||
}
|
|
||||||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
|
||||||
json["origin"] = this.origin.getUid();
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
};
|
|
||||||
|
|
||||||
return Word;
|
|
||||||
|
|
||||||
})(types.ListManager);
|
|
||||||
parser['Word'] = function(json) {
|
|
||||||
var beginning, end, next, origin, prev, uid;
|
|
||||||
uid = json['uid'], beginning = json['beginning'], end = json['end'], prev = json['prev'], next = json['next'], origin = json['origin'];
|
|
||||||
return new Word(uid, beginning, end, prev, next, origin);
|
|
||||||
};
|
|
||||||
types['TextInsert'] = TextInsert;
|
|
||||||
types['TextDelete'] = TextDelete;
|
|
||||||
types['Word'] = Word;
|
|
||||||
return structured_types;
|
|
||||||
};
|
|
||||||
|
|
||||||
//# sourceMappingURL=TextTypes.js.map
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user