Documentation and cleanup
This commit is contained in:
@@ -25,6 +25,9 @@ createIwcConnector = (callback, options)->
|
||||
|
||||
#
|
||||
# The Iwc Connector adds support for the Inter-Widget-Communication protocol that is used in the Role-SDK.
|
||||
#
|
||||
# You must not use your own IWC client when using this connector!!
|
||||
#
|
||||
# @see http://dbis.rwth-aachen.de/cms/projects/the-xmpp-experience#interwidget-communication
|
||||
# @see http://dbis.rwth-aachen.de/cms/projects/ROLE
|
||||
#
|
||||
@@ -34,7 +37,7 @@ createIwcConnector = (callback, options)->
|
||||
# @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.
|
||||
# @param {YattaFramework} yatta The Yatta framework.
|
||||
#
|
||||
constructor: (@engine, @HB, @execution_listener, @yatta)->
|
||||
@duiClient = duiClient
|
||||
@@ -75,20 +78,11 @@ createIwcConnector = (callback, options)->
|
||||
@iwcHandler["Yatta_get_HB_element"] = [sendHistoryBuffer]
|
||||
|
||||
#
|
||||
# This function is called whenever an operation was executed.
|
||||
# @param {Operation} o The operation that was executed.
|
||||
# Set your own IWC handler. It will be called after Yatta consumed the
|
||||
# data from the received intent.
|
||||
#
|
||||
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
|
||||
setIwcHandler: (f)->
|
||||
userIwcHandler = f
|
||||
|
||||
#
|
||||
# Helper for sending iwc intents.
|
||||
@@ -114,8 +108,23 @@ createIwcConnector = (callback, options)->
|
||||
|
||||
@duiClient.sendIntent(intent)
|
||||
|
||||
setIwcHandler: (f)->
|
||||
userIwcHandler = f
|
||||
#
|
||||
# @private
|
||||
# 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
|
||||
|
||||
#
|
||||
# @private
|
||||
# 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
|
||||
|
||||
|
||||
init = ()->
|
||||
|
||||
@@ -19,6 +19,8 @@ createPeerJsConnector = ()->
|
||||
|
||||
|
||||
#
|
||||
# PeerJs is a Framework that enables you to connect to other peers. You just need the
|
||||
# user-id of the peer (browser/client). And then you can connect to it.
|
||||
# @see http://peerjs.com
|
||||
#
|
||||
class PeerJsConnector
|
||||
@@ -38,25 +40,46 @@ createPeerJsConnector = ()->
|
||||
@addConnection conn
|
||||
|
||||
send_ = (o)=>
|
||||
@send o
|
||||
if o.uid.creator is @HB.getUserId() and (typeof o.uid.op_number isnt "string")
|
||||
for conn_id,conn of @connections
|
||||
conn.send
|
||||
op: o
|
||||
@execution_listener.push send_
|
||||
|
||||
#
|
||||
# Connect the Framework to another peer. Therefore you have to receive his
|
||||
# user_id. If the other peer is connected to other peers, the PeerJsConnector
|
||||
# will automatically connect to them too.
|
||||
#
|
||||
# Transmitting the user_id is your job.
|
||||
# See [TextEditing](../../examples/TextEditing/) for a nice example
|
||||
# on how to do that with urls.
|
||||
#
|
||||
# @param id {String} Connection id
|
||||
#
|
||||
connectToPeer: (id)->
|
||||
if not @connections[id]? and id isnt @yatta.getUserId()
|
||||
@addConnection peer.connect id
|
||||
|
||||
#
|
||||
# Receive the id of every connected peer.
|
||||
# @return {Array<String>} A list of Peer-Ids
|
||||
#
|
||||
getAllConnectionIds: ()->
|
||||
for conn_id of @connections
|
||||
conn_id
|
||||
|
||||
#
|
||||
# What this method does:
|
||||
# * Send state vector
|
||||
# * Receive HB -> apply them
|
||||
# * Send connections
|
||||
# * Receive Connections -> Connect to unknow connections
|
||||
# Adds an existing connection to this connector.
|
||||
# @param conn {PeerJsConnection}
|
||||
#
|
||||
addConnection: (conn)->
|
||||
#
|
||||
# What this method does:
|
||||
# * Send state vector
|
||||
# * Receive HB -> apply them
|
||||
# * Send connections
|
||||
# * Receive Connections -> Connect to unknow connections
|
||||
@connections[conn.peer] = conn
|
||||
initialized_me = false
|
||||
initialized_him = false
|
||||
@@ -91,24 +114,6 @@ createPeerJsConnector = ()->
|
||||
setTimeout sendStateVector, 100
|
||||
sendStateVector()
|
||||
|
||||
#
|
||||
# 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 conn_id,conn of @connections
|
||||
conn.send
|
||||
op: o
|
||||
|
||||
#
|
||||
# This function is called whenever an operation was received from another peer.
|
||||
# @param {Operation} o The operation that was received.
|
||||
#
|
||||
receive: (o)->
|
||||
if o.uid.creator isnt @HB.getUserId()
|
||||
@engine.applyOp o
|
||||
|
||||
peer.on 'open', (id)->
|
||||
callback PeerJsConnector, id
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ _ = require "underscore"
|
||||
module.exports = (user_list)->
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# A trivial Connector that simulates network delay.
|
||||
#
|
||||
class TestConnector
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# The Engine handles how and in which order to execute operations and add operations to the HistoryBuffer.
|
||||
#
|
||||
class Engine
|
||||
|
||||
@@ -10,7 +10,7 @@ Engine = require "../Engine"
|
||||
# * Integer
|
||||
# * Array
|
||||
#
|
||||
class JsonYatta
|
||||
class JsonFramework
|
||||
|
||||
#
|
||||
# @param {String} user_id Unique id of the peer.
|
||||
@@ -22,23 +22,16 @@ class JsonYatta
|
||||
@types = type_manager.types
|
||||
@engine = new Engine @HB, type_manager.parser
|
||||
@connector = new Connector @engine, @HB, type_manager.execution_listener, @
|
||||
|
||||
first_word = new @types.JsonType @HB.getReservedUniqueIdentifier()
|
||||
@HB.addOperation(first_word).execute()
|
||||
@root_element = first_word
|
||||
|
||||
#
|
||||
# @result JsonType
|
||||
# @return JsonType
|
||||
#
|
||||
getSharedObject: ()->
|
||||
@root_element
|
||||
|
||||
#
|
||||
# @see Engine
|
||||
#
|
||||
getEngine: ()->
|
||||
@engine
|
||||
|
||||
#
|
||||
# Get the initialized connector.
|
||||
#
|
||||
@@ -60,7 +53,7 @@ class JsonYatta
|
||||
#
|
||||
# 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).
|
||||
# JsonFramework was initialized (Depending on the HistoryBuffer implementation).
|
||||
#
|
||||
getUserId: ()->
|
||||
@HB.getUserId()
|
||||
@@ -77,16 +70,22 @@ class JsonYatta
|
||||
val : (name, content, mutable)->
|
||||
@root_element.val(name, content, mutable)
|
||||
|
||||
#
|
||||
# @see Operation.on
|
||||
#
|
||||
on: ()->
|
||||
@root_element.on arguments...
|
||||
|
||||
#
|
||||
# @see Operation.deleteListener
|
||||
#
|
||||
deleteListener: ()->
|
||||
@root_element.deleteListener arguments...
|
||||
|
||||
#
|
||||
# @see JsonType.value
|
||||
#
|
||||
Object.defineProperty JsonYatta.prototype, 'value',
|
||||
Object.defineProperty JsonFramework.prototype, 'value',
|
||||
get : -> @root_element.value
|
||||
set : (o)->
|
||||
if o.constructor is {}.constructor
|
||||
@@ -95,8 +94,8 @@ class JsonYatta
|
||||
else
|
||||
throw new Error "You must only set Object values!"
|
||||
|
||||
module.exports = JsonYatta
|
||||
module.exports = JsonFramework
|
||||
if window?
|
||||
if not window.Y?
|
||||
window.Y = {}
|
||||
window.Y.JsonYatta = JsonYatta
|
||||
window.Y.JsonFramework = JsonFramework
|
||||
@@ -6,7 +6,7 @@ Engine = require "../Engine"
|
||||
#
|
||||
# Framework for Text Datastructures.
|
||||
#
|
||||
class TextYatta
|
||||
class TextFramework
|
||||
|
||||
#
|
||||
# @param {String} user_id Uniqe user id that defines this peer.
|
||||
@@ -24,7 +24,7 @@ class TextYatta
|
||||
beginning.next_cl = end
|
||||
beginning.execute()
|
||||
end.execute()
|
||||
first_word = new @types.Word {creator: '_', op_number: '_'}, beginning, end
|
||||
first_word = new @types.WordType {creator: '_', op_number: '_'}, beginning, end
|
||||
@HB.addOperation(first_word).execute()
|
||||
|
||||
uid_r = { creator: '_', op_number: "RM" }
|
||||
@@ -37,17 +37,11 @@ class TextYatta
|
||||
|
||||
|
||||
#
|
||||
# @result Word
|
||||
# @return WordType
|
||||
#
|
||||
getSharedObject: ()->
|
||||
@root_element.val()
|
||||
|
||||
#
|
||||
# @see Engine
|
||||
#
|
||||
getEngine: ()->
|
||||
@engine
|
||||
|
||||
#
|
||||
# Get the initialized connector.
|
||||
#
|
||||
@@ -63,7 +57,7 @@ class TextYatta
|
||||
#
|
||||
# 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).
|
||||
# JsonFramework was initialized (Depending on the HistoryBuffer implementation).
|
||||
#
|
||||
getUserId: ()->
|
||||
@HB.getUserId()
|
||||
@@ -75,35 +69,38 @@ class TextYatta
|
||||
@getSharedObject().val()
|
||||
|
||||
#
|
||||
# @see Word.insertText
|
||||
# @see WordType.insertText
|
||||
#
|
||||
insertText: (pos, content)->
|
||||
@getSharedObject().insertText pos, content
|
||||
|
||||
#
|
||||
# @see Word.deleteText
|
||||
# @see WordType.deleteText
|
||||
#
|
||||
deleteText: (pos, length)->
|
||||
@getSharedObject().deleteText pos, length
|
||||
|
||||
#
|
||||
# @see Word.bind
|
||||
# @see WordType.bind
|
||||
#
|
||||
bind: (textarea)->
|
||||
@getSharedObject().bind textarea
|
||||
|
||||
#
|
||||
# @see Word.replaceText
|
||||
# @see WordType.replaceText
|
||||
#
|
||||
replaceText: (text)->
|
||||
@getSharedObject().replaceText text
|
||||
|
||||
#
|
||||
# @see Operation.on
|
||||
#
|
||||
on: ()->
|
||||
@root_element.on arguments...
|
||||
|
||||
|
||||
module.exports = TextYatta
|
||||
module.exports = TextFramework
|
||||
if window?
|
||||
if not window.Y?
|
||||
window.Y = {}
|
||||
window.Y.TextYatta = TextYatta
|
||||
window.Y.TextFramework = TextFramework
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# An object that holds all applied operations.
|
||||
#
|
||||
# @note The HistoryBuffer is commonly abbreviated to HB.
|
||||
|
||||
@@ -4,14 +4,17 @@ module.exports = (HB)->
|
||||
execution_listener = []
|
||||
|
||||
#
|
||||
# @private
|
||||
# @abstract
|
||||
# @nodoc
|
||||
# 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
|
||||
# * _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.
|
||||
# Furthermore an encodable operation has a parser. We extend the parser object in order to parse encoded operations.
|
||||
#
|
||||
class Operation
|
||||
|
||||
@@ -40,6 +43,16 @@ module.exports = (HB)->
|
||||
@event_listeners[e] ?= []
|
||||
@event_listeners[e].push f
|
||||
|
||||
#
|
||||
# Deletes a function from an event / list of events.
|
||||
# @see Operation.on
|
||||
#
|
||||
# @overload deleteListener(event, f)
|
||||
# @param event {String} An event name
|
||||
# @param f {Function} The function that you want to delete from these events
|
||||
# @overload deleteListener(events, f)
|
||||
# @param events {Array<String>} A list of event names
|
||||
# @param f {Function} The function that you want to delete from these events.
|
||||
deleteListener: (events, f)->
|
||||
if events.constructor isnt [].constructor
|
||||
events = [events]
|
||||
@@ -148,6 +161,7 @@ module.exports = (HB)->
|
||||
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# A simple Delete-type operation that deletes an Insert-type operation.
|
||||
#
|
||||
class Delete extends Operation
|
||||
@@ -194,6 +208,7 @@ module.exports = (HB)->
|
||||
new Delete uid, deletes_uid
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# A simple insert-type operation.
|
||||
#
|
||||
# An insert operation is always positioned between two other insert operations.
|
||||
@@ -350,7 +365,9 @@ module.exports = (HB)->
|
||||
position++
|
||||
prev = prev.prev_cl
|
||||
position
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# Defines an object that is cannot be changed. You can use this to set an immutable string, or a number.
|
||||
#
|
||||
class ImmutableObject extends Insert
|
||||
@@ -396,6 +413,7 @@ module.exports = (HB)->
|
||||
new ImmutableObject uid, content, prev, next, origin
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# 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.
|
||||
|
||||
@@ -5,15 +5,17 @@ module.exports = (HB)->
|
||||
types = text_types.types
|
||||
parser = text_types.parser
|
||||
|
||||
createJsonWrapper = (_jsonType)->
|
||||
createJsonTypeWrapper = (_jsonType)->
|
||||
|
||||
#
|
||||
# A JsonWrapper was intended to be a convenient wrapper for the JsonType.
|
||||
# @note EXPERIMENTAL
|
||||
#
|
||||
# A JsonTypeWrapper 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
|
||||
# @example create a JsonTypeWrapper
|
||||
# # You get a JsonTypeWrapper from a JsonType by calling
|
||||
# w = yatta.value
|
||||
#
|
||||
# It creates Javascripts -getter and -setter methods for each property that JsonType maintains.
|
||||
@@ -34,10 +36,10 @@ module.exports = (HB)->
|
||||
# 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
|
||||
# Therefore the JsonTypeWrapper 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
|
||||
# If you overwrite an object property of the JsonTypeWrapper with a new object, it will result in a merged version of the objects.
|
||||
# Let `yatta.value.p` the property that is to be overwritten and o the new value. E.g. `yatta.value.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.
|
||||
#
|
||||
@@ -63,7 +65,7 @@ module.exports = (HB)->
|
||||
# yatta.value = {newProperty : "Awesome"}
|
||||
# console.log(w.newProperty == "Awesome") # true!
|
||||
#
|
||||
class JsonWrapper
|
||||
class JsonTypeWrapper
|
||||
|
||||
#
|
||||
# @param {JsonType} jsonType Instance of the JsonType that this class wrappes.
|
||||
@@ -71,11 +73,11 @@ module.exports = (HB)->
|
||||
constructor: (jsonType)->
|
||||
for name, obj of jsonType.map
|
||||
do (name, obj)->
|
||||
Object.defineProperty JsonWrapper.prototype, name,
|
||||
Object.defineProperty JsonTypeWrapper.prototype, name,
|
||||
get : ->
|
||||
x = obj.val()
|
||||
if x instanceof JsonType
|
||||
createJsonWrapper x
|
||||
createJsonTypeWrapper x
|
||||
else if x instanceof types.ImmutableObject
|
||||
x.val()
|
||||
else
|
||||
@@ -89,7 +91,7 @@ module.exports = (HB)->
|
||||
jsonType.val(name, o, 'immutable')
|
||||
enumerable: true
|
||||
configurable: false
|
||||
new JsonWrapper _jsonType
|
||||
new JsonTypeWrapper _jsonType
|
||||
|
||||
#
|
||||
# Manages Object-like values.
|
||||
@@ -109,6 +111,18 @@ module.exports = (HB)->
|
||||
for name,o of initial_value
|
||||
@val name, o, mutable
|
||||
|
||||
#
|
||||
# Identifies this class.
|
||||
# Use it to check whether this is a json-type or something else.
|
||||
#
|
||||
# @example
|
||||
# var x = yatta.val('unknown')
|
||||
# if (x.type === "JsonType") {
|
||||
# console.log JSON.stringify(x.toJson())
|
||||
# }
|
||||
#
|
||||
type: "JsonType"
|
||||
|
||||
#
|
||||
# Transform this to a Json and loose all the sharing-abilities (the new object will be a deep clone)!
|
||||
# @return {Json}
|
||||
@@ -128,7 +142,7 @@ module.exports = (HB)->
|
||||
json
|
||||
|
||||
#
|
||||
# @see Word.setReplaceManager
|
||||
# @see WordType.setReplaceManager
|
||||
# Sets the parent of this JsonType object.
|
||||
#
|
||||
setReplaceManager: (rm)->
|
||||
@@ -168,7 +182,7 @@ module.exports = (HB)->
|
||||
# @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.
|
||||
# @return [JsonType|WordType|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.
|
||||
@@ -198,7 +212,7 @@ module.exports = (HB)->
|
||||
super name, obj
|
||||
else
|
||||
if typeof content is 'string'
|
||||
word = HB.addOperation(new types.Word undefined).execute()
|
||||
word = HB.addOperation(new types.WordType undefined).execute()
|
||||
word.insertText 0, content
|
||||
super name, word
|
||||
else if content.constructor is Object
|
||||
@@ -210,7 +224,7 @@ module.exports = (HB)->
|
||||
super name, content
|
||||
|
||||
Object.defineProperty JsonType.prototype, 'value',
|
||||
get : -> createJsonWrapper @
|
||||
get : -> createJsonTypeWrapper @
|
||||
set : (o)->
|
||||
if o.constructor is {}.constructor
|
||||
for o_name,o_obj of o
|
||||
|
||||
@@ -6,6 +6,7 @@ module.exports = (HB)->
|
||||
parser = basic_types.parser
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# Manages map like objects. E.g. Json-Type and XML attributes.
|
||||
#
|
||||
class MapManager extends types.Operation
|
||||
@@ -42,6 +43,7 @@ module.exports = (HB)->
|
||||
result
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# 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
|
||||
@@ -102,6 +104,7 @@ module.exports = (HB)->
|
||||
new AddName uid, map_manager, name
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# Manages a list of Insert-type operations.
|
||||
#
|
||||
class ListManager extends types.Insert
|
||||
@@ -123,6 +126,10 @@ module.exports = (HB)->
|
||||
@end.execute()
|
||||
super uid, prev, next, origin
|
||||
|
||||
#
|
||||
# @private
|
||||
# @see Operation.execute
|
||||
#
|
||||
execute: ()->
|
||||
if @validateSavedOperations()
|
||||
@beginning.setParent @
|
||||
@@ -170,11 +177,12 @@ module.exports = (HB)->
|
||||
o
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# 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
|
||||
# The WordType-type has implemented support for replace
|
||||
# @see WordType
|
||||
#
|
||||
class ReplaceManager extends ListManager
|
||||
#
|
||||
@@ -214,8 +222,9 @@ module.exports = (HB)->
|
||||
@deleteListener 'addProperty', addPropertyListener
|
||||
@on 'insert', addPropertyListener
|
||||
super parent
|
||||
|
||||
#
|
||||
# Get the value of this Word
|
||||
# Get the value of this WordType
|
||||
# @return {String}
|
||||
#
|
||||
val: ()->
|
||||
@@ -256,6 +265,7 @@ module.exports = (HB)->
|
||||
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# The ReplaceManager manages Replaceables.
|
||||
# @see ReplaceManager
|
||||
#
|
||||
@@ -287,7 +297,7 @@ module.exports = (HB)->
|
||||
|
||||
#
|
||||
# If possible set the replace manager in the content.
|
||||
# @see Word.setReplaceManager
|
||||
# @see WordType.setReplaceManager
|
||||
#
|
||||
execute: ()->
|
||||
if not @validateSavedOperations()
|
||||
|
||||
@@ -6,6 +6,7 @@ module.exports = (HB)->
|
||||
parser = structured_types.parser
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
# At the moment TextDelete type equals the Delete type in BasicTypes.
|
||||
# @see BasicTypes.Delete
|
||||
#
|
||||
@@ -13,7 +14,8 @@ module.exports = (HB)->
|
||||
parser["TextDelete"] = parser["Delete"]
|
||||
|
||||
#
|
||||
# Extends the basic Insert type to an operation that holds a text value
|
||||
# @nodoc
|
||||
# Extends the basic Insert type to an operation that holds a text value
|
||||
#
|
||||
class TextInsert extends types.Insert
|
||||
#
|
||||
@@ -72,28 +74,47 @@ module.exports = (HB)->
|
||||
new TextInsert content, uid, prev, next, origin
|
||||
|
||||
#
|
||||
# Handles a Text-like data structures with support for insertText/deleteText at a word-position.
|
||||
# Handles a WordType-like data structures with support for insertText/deleteText at a word-position.
|
||||
# @note Currently, only Text is supported!
|
||||
#
|
||||
class Word extends types.ListManager
|
||||
class WordType extends types.ListManager
|
||||
|
||||
#
|
||||
# @private
|
||||
# @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
|
||||
# Identifies this class.
|
||||
# Use it to check whether this is a word-type or something else.
|
||||
#
|
||||
# @example
|
||||
# var x = yatta.val('unknown')
|
||||
# if (x.type === "WordType") {
|
||||
# console.log JSON.stringify(x.toJson())
|
||||
# }
|
||||
#
|
||||
type: "WordType"
|
||||
|
||||
#
|
||||
# Inserts a string into the word.
|
||||
#
|
||||
# @return {WordType} This WordType object.
|
||||
#
|
||||
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.
|
||||
#
|
||||
# @return {WordType} This WordType object
|
||||
#
|
||||
deleteText: (position, length)->
|
||||
o = @getOperationByPosition position
|
||||
|
||||
@@ -106,25 +127,28 @@ module.exports = (HB)->
|
||||
while not (o instanceof types.Delimiter) and o.isDeleted()
|
||||
o = o.next_cl
|
||||
delete_ops.push d._encode()
|
||||
delete_ops
|
||||
@
|
||||
|
||||
#
|
||||
# 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
|
||||
# @return {WordType} Returns the new WordType object.
|
||||
#
|
||||
replaceText: (text)->
|
||||
# Can only be used if the ReplaceManager was set!
|
||||
# @see WordType.setReplaceManager
|
||||
if @replace_manager?
|
||||
word = HB.addOperation(new Word undefined).execute()
|
||||
word = HB.addOperation(new WordType undefined).execute()
|
||||
word.insertText 0, text
|
||||
@replace_manager.replace(word)
|
||||
word
|
||||
else
|
||||
throw new Error "This type is currently not maintained by a ReplaceManager!"
|
||||
|
||||
#
|
||||
# @returns [Json] A Json object.
|
||||
# Get the String-representation of this word.
|
||||
# @return {String} The String-representation of this object.
|
||||
#
|
||||
val: ()->
|
||||
c = for o in @toArray()
|
||||
@@ -135,7 +159,15 @@ module.exports = (HB)->
|
||||
c.join('')
|
||||
|
||||
#
|
||||
# In most cases you would embed a Word in a Replaceable, wich is handled by the ReplaceManager in order
|
||||
# Same as WordType.val
|
||||
# @see WordType.val
|
||||
#
|
||||
toString: ()->
|
||||
@val()
|
||||
|
||||
#
|
||||
# @private
|
||||
# In most cases you would embed a WordType in a Replaceable, wich is handled by the ReplaceManager in order
|
||||
# to provide replace functionality.
|
||||
#
|
||||
setReplaceManager: (op)->
|
||||
@@ -145,7 +177,11 @@ module.exports = (HB)->
|
||||
@replace_manager?.callEvent 'change'
|
||||
|
||||
#
|
||||
# Bind this Word to a textfield.
|
||||
# Bind this WordType to a textfield or input field.
|
||||
#
|
||||
# @example
|
||||
# var textbox = document.getElementById("textfield");
|
||||
# yatta.bind(textbox);
|
||||
#
|
||||
bind: (textfield)->
|
||||
word = @
|
||||
@@ -250,11 +286,12 @@ module.exports = (HB)->
|
||||
|
||||
|
||||
#
|
||||
# @private
|
||||
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||
#
|
||||
_encode: ()->
|
||||
json = {
|
||||
'type': "Word"
|
||||
'type': "WordType"
|
||||
'uid' : @getUid()
|
||||
'beginning' : @beginning.getUid()
|
||||
'end' : @end.getUid()
|
||||
@@ -267,7 +304,7 @@ module.exports = (HB)->
|
||||
json["origin"] = @origin.getUid()
|
||||
json
|
||||
|
||||
parser['Word'] = (json)->
|
||||
parser['WordType'] = (json)->
|
||||
{
|
||||
'uid' : uid
|
||||
'beginning' : beginning
|
||||
@@ -276,11 +313,11 @@ module.exports = (HB)->
|
||||
'next': next
|
||||
'origin' : origin
|
||||
} = json
|
||||
new Word uid, beginning, end, prev, next, origin
|
||||
new WordType uid, beginning, end, prev, next, origin
|
||||
|
||||
types['TextInsert'] = TextInsert
|
||||
types['TextDelete'] = TextDelete
|
||||
types['Word'] = Word
|
||||
types['WordType'] = WordType
|
||||
structured_types
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
|
||||
|
||||
exports['IwcConnector'] =
|
||||
require './Connectors/IwcConnector'
|
||||
exports['TestConnector'] =
|
||||
require './Connectors/TestConnector'
|
||||
exports['JsonYatta'] =
|
||||
require './Frameworks/JsonYatta'
|
||||
exports['TextYatta'] =
|
||||
require './Frameworks/TextYatta'
|
||||
exports['JsonFramework'] =
|
||||
require './Frameworks/JsonFramework'
|
||||
exports['TextFramework'] =
|
||||
require './Frameworks/TextFramework'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user