Added cool json features (JsonWrapper)
This commit is contained in:
@@ -41,7 +41,7 @@ createIwcConnector = (callback)->
|
||||
sendRootElement = ()=>
|
||||
json = {
|
||||
root_element : @yatta.getRootElement()
|
||||
HB : @yatta.getHistoryBuffer().toJson()
|
||||
HB : @yatta.getHistoryBuffer()._encode()
|
||||
}
|
||||
@sendIwcIntent "Yatta_push_root_element", json
|
||||
@iwcHandler["Yatta_get_root_element"] = [sendRootElement]
|
||||
@@ -94,5 +94,5 @@ createIwcConnector = (callback)->
|
||||
|
||||
undefined
|
||||
module.exports = createIwcConnector
|
||||
window?.createIwcConnector = createIwcConnector
|
||||
window?.createConnector = createIwcConnector
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = (user_list)->
|
||||
@applied_operations.push o
|
||||
@execution_listener.push appliedOperationsListener
|
||||
if not (user_list?.length is 0)
|
||||
@engine.applyOps user_list[0].getHistoryBuffer().toJson()
|
||||
@engine.applyOps user_list[0].getHistoryBuffer()._encode()
|
||||
|
||||
@unexecuted = {}
|
||||
|
||||
|
||||
@@ -22,9 +22,17 @@ class Engine
|
||||
for o in ops
|
||||
if not o.execute()
|
||||
@unprocessed_ops.push o
|
||||
@cleanUp()
|
||||
@tryUnprocessed()
|
||||
|
||||
cleanUp: ()->
|
||||
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.addOperation o
|
||||
if not o.execute()
|
||||
@unprocessed_ops.push o
|
||||
@tryUnprocessed()
|
||||
|
||||
tryUnprocessed: ()->
|
||||
while true
|
||||
old_length = @unprocessed_ops.length
|
||||
unprocessed = []
|
||||
@@ -35,15 +43,7 @@ class Engine
|
||||
if @unprocessed_ops.length is old_length
|
||||
break
|
||||
|
||||
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.addOperation o
|
||||
if not o.execute()
|
||||
@unprocessed_ops.push o
|
||||
@cleanUp()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = Engine
|
||||
|
||||
@@ -4,7 +4,11 @@ HistoryBuffer = require "../HistoryBuffer.coffee"
|
||||
Engine = require "../Engine.coffee"
|
||||
|
||||
#
|
||||
# Framework for arbitrary Json data-structures.
|
||||
# Framework for Json data-structures.
|
||||
# Known values that are supported:
|
||||
# * String
|
||||
# * Integer
|
||||
# * Array
|
||||
#
|
||||
class JsonYatta
|
||||
constructor: (user_id, Connector)->
|
||||
@@ -21,23 +25,55 @@ class JsonYatta
|
||||
else
|
||||
@root_element = @HB.getOperation(root_elem)
|
||||
|
||||
#
|
||||
# @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()
|
||||
|
||||
val: (name, content)->
|
||||
@root_element.val(name, content)
|
||||
#
|
||||
# @see JsonType.val
|
||||
#
|
||||
val : (name, content, mutable)->
|
||||
@root_element.val(name, content, mutable)
|
||||
|
||||
#
|
||||
# @see JsonType.value
|
||||
#
|
||||
value : ()->
|
||||
@root_element.value
|
||||
|
||||
window?.JsonYatta = JsonYatta
|
||||
module.exports = JsonYatta
|
||||
|
||||
@@ -30,12 +30,12 @@ class HistoryBuffer
|
||||
res[user] = ctn
|
||||
res
|
||||
|
||||
toJson: ()->
|
||||
_encode: ()->
|
||||
json = []
|
||||
for u_name,user of @buffer
|
||||
for o_number,o of user
|
||||
if not isNaN(parseInt(o_number))
|
||||
json.push o.toJson()
|
||||
json.push o._encode()
|
||||
json
|
||||
|
||||
#
|
||||
|
||||
@@ -7,35 +7,44 @@ module.exports = (HB)->
|
||||
# A generic interface to operations.
|
||||
#
|
||||
# An operation has the following methods:
|
||||
# toJson: encodes an operation (needed only if instance of this operation is sent).
|
||||
# _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
|
||||
|
||||
#
|
||||
# @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
|
||||
|
||||
# Computes a unique identifier (uid).
|
||||
#
|
||||
# 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 @toJson()
|
||||
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.
|
||||
@@ -68,6 +77,7 @@ module.exports = (HB)->
|
||||
@unchecked[name] = op
|
||||
|
||||
#
|
||||
# @private
|
||||
# After calling this function all not instantiated operations will be accessible.
|
||||
# @see Operation.saveOperation
|
||||
#
|
||||
@@ -94,15 +104,21 @@ module.exports = (HB)->
|
||||
# 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.
|
||||
#
|
||||
toJson: ()->
|
||||
_encode: ()->
|
||||
{
|
||||
'type': "Delete"
|
||||
'uid': @getUid()
|
||||
@@ -110,6 +126,7 @@ module.exports = (HB)->
|
||||
}
|
||||
|
||||
#
|
||||
# @private
|
||||
# Apply the deletion.
|
||||
#
|
||||
execute: ()->
|
||||
@@ -142,8 +159,7 @@ module.exports = (HB)->
|
||||
class Insert extends Operation
|
||||
|
||||
#
|
||||
# @param {Object} creator A unique user identifier
|
||||
# @param {Integer} op_number This Number was assigned via getNextOperationIdentifier().
|
||||
# @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)
|
||||
#
|
||||
@@ -158,6 +174,9 @@ module.exports = (HB)->
|
||||
@saveOperation 'origin', prev_cl
|
||||
super uid
|
||||
|
||||
#
|
||||
# @private
|
||||
#
|
||||
applyDelete: (o)->
|
||||
@deleted_by ?= []
|
||||
@deleted_by.push o
|
||||
@@ -169,6 +188,7 @@ module.exports = (HB)->
|
||||
@deleted_by?.length > 0
|
||||
|
||||
#
|
||||
# @private
|
||||
# The amount of positions that $this operation was moved to the right.
|
||||
#
|
||||
getDistanceToOrigin: ()->
|
||||
@@ -185,6 +205,7 @@ module.exports = (HB)->
|
||||
d
|
||||
|
||||
#
|
||||
# @private
|
||||
# Update the short list
|
||||
# TODO (Unused)
|
||||
update_sl: ()->
|
||||
@@ -203,6 +224,7 @@ module.exports = (HB)->
|
||||
|
||||
|
||||
#
|
||||
# @private
|
||||
# Include this operation in the associative lists.
|
||||
#
|
||||
execute: ()->
|
||||
@@ -263,8 +285,47 @@ module.exports = (HB)->
|
||||
super # notify the execution_listeners
|
||||
@
|
||||
|
||||
val: ()->
|
||||
throw new Error "Implement this function!"
|
||||
#
|
||||
# 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: ()->
|
||||
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.
|
||||
@@ -273,21 +334,21 @@ module.exports = (HB)->
|
||||
#
|
||||
class Delimiter extends Insert
|
||||
|
||||
isDeleted: ()->
|
||||
false
|
||||
|
||||
getDistanceToOrigin: ()->
|
||||
0
|
||||
|
||||
#
|
||||
# @private
|
||||
#
|
||||
execute: ()->
|
||||
if @validateSavedOperations()
|
||||
for l in execution_listener
|
||||
l @toJson()
|
||||
l @_encode()
|
||||
@
|
||||
else
|
||||
false
|
||||
|
||||
toJson: ()->
|
||||
#
|
||||
# @private
|
||||
#
|
||||
_encode: ()->
|
||||
{
|
||||
'type' : "Delimiter"
|
||||
'uid' : @getUid()
|
||||
@@ -310,6 +371,7 @@ module.exports = (HB)->
|
||||
'Insert' : Insert
|
||||
'Delimiter': Delimiter
|
||||
'Operation': Operation
|
||||
'ImmutableObject' : ImmutableObject
|
||||
'parser' : parser
|
||||
'execution_listener' : execution_listener
|
||||
}
|
||||
|
||||
@@ -5,48 +5,179 @@ module.exports = (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 getter 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
|
||||
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
|
||||
constructor: (uid, initial_value)->
|
||||
|
||||
#
|
||||
# @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
|
||||
@val name, o, mutable
|
||||
|
||||
mutable_default:
|
||||
true
|
||||
|
||||
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'
|
||||
|
||||
#
|
||||
# Get this as a Json object. Note that none of the values of the result is of type Operation.
|
||||
# @overload val()
|
||||
# @results [Json]
|
||||
# Get this as a Json object.
|
||||
# @return [Json]
|
||||
#
|
||||
# Get value of a property.
|
||||
# @overload val(name)
|
||||
# Get value of a property.
|
||||
# @param {String} name Name of the object property.
|
||||
# @results [JsonType|WordType]
|
||||
# @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.
|
||||
#
|
||||
# Set a new property.
|
||||
# @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)->
|
||||
if name? and content?
|
||||
if typeof content is 'string'
|
||||
word = HB.addOperation(new types.Word HB.getNextOperationIdentifier(), content).execute()
|
||||
super name, word
|
||||
else if typeof content is 'object'
|
||||
json = HB.addOperation(JsonType HB.getNextOperationIdentifier(), content).execute()
|
||||
super name, json
|
||||
else
|
||||
throw new Error "You must not set #{typeof content}-types in collaborative Json-objects!"
|
||||
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 HB.getNextOperationIdentifier(), content).execute()
|
||||
super name, word
|
||||
else if content.constructor is Object
|
||||
json = HB.addOperation(new JsonType HB.getNextOperationIdentifier(), 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
|
||||
|
||||
toJson: ()->
|
||||
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()
|
||||
@@ -59,6 +190,8 @@ module.exports = (HB)->
|
||||
new JsonType uid
|
||||
|
||||
|
||||
|
||||
|
||||
types['JsonType'] = JsonType
|
||||
|
||||
text_types
|
||||
|
||||
@@ -9,6 +9,10 @@ module.exports = (HB)->
|
||||
# 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
|
||||
@@ -18,12 +22,20 @@ module.exports = (HB)->
|
||||
if not @map[name]?
|
||||
HB.addOperation(new AddName HB.getNextOperationIdentifier(), @, name).execute()
|
||||
@map[name].replace content
|
||||
@
|
||||
else if name?
|
||||
@map[name]?.val()
|
||||
obj = @map[name]?.val()
|
||||
if obj instanceof types.ImmutableObject
|
||||
obj.val()
|
||||
else
|
||||
obj
|
||||
else
|
||||
result = {}
|
||||
for name,o of @map
|
||||
result[name] = o.val()
|
||||
obj = o.val()
|
||||
if obj instanceof types.ImmutableObject or obj instanceof MapManager
|
||||
obj = obj.val()
|
||||
result[name] = obj
|
||||
result
|
||||
|
||||
#
|
||||
@@ -33,6 +45,12 @@ module.exports = (HB)->
|
||||
# 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
|
||||
@@ -54,7 +72,7 @@ module.exports = (HB)->
|
||||
@map_manager.map[@name] = HB.addOperation(new ReplaceManager undefined, uid_r, beg, end).execute()
|
||||
super
|
||||
|
||||
toJson: ()->
|
||||
_encode: ()->
|
||||
{
|
||||
'type' : "AddName"
|
||||
'uid' : @getUid()
|
||||
@@ -74,6 +92,12 @@ module.exports = (HB)->
|
||||
# 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
|
||||
@@ -129,6 +153,11 @@ module.exports = (HB)->
|
||||
# @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?
|
||||
@@ -145,7 +174,7 @@ module.exports = (HB)->
|
||||
throw new Error "dtrn"
|
||||
o.val()
|
||||
|
||||
toJson: ()->
|
||||
_encode: ()->
|
||||
json =
|
||||
{
|
||||
'type': "ReplaceManager"
|
||||
@@ -178,6 +207,12 @@ module.exports = (HB)->
|
||||
# @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
|
||||
@@ -203,7 +238,7 @@ module.exports = (HB)->
|
||||
# Convert all relevant information of this operation to the json-format.
|
||||
# This result can be send to other clients.
|
||||
#
|
||||
toJson: ()->
|
||||
_encode: ()->
|
||||
json =
|
||||
{
|
||||
'type': "Replaceable"
|
||||
|
||||
@@ -16,6 +16,10 @@ module.exports = (HB)->
|
||||
# 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!"
|
||||
@@ -44,7 +48,7 @@ module.exports = (HB)->
|
||||
# Convert all relevant information of this operation to the json-format.
|
||||
# This result can be send to other clients.
|
||||
#
|
||||
toJson: ()->
|
||||
_encode: ()->
|
||||
json =
|
||||
{
|
||||
'type': "TextInsert"
|
||||
@@ -71,6 +75,11 @@ module.exports = (HB)->
|
||||
# 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.
|
||||
# @param {String} initial_content
|
||||
#
|
||||
constructor: (uid, initial_content, beginning, end, prev, next, origin)->
|
||||
super uid, beginning, end, prev, next, origin
|
||||
if initial_content?
|
||||
@@ -97,7 +106,7 @@ module.exports = (HB)->
|
||||
if o instanceof types.Delimiter
|
||||
throw new Error "You can't delete more than there is.."
|
||||
o = o.next_cl
|
||||
d.toJson()
|
||||
d._encode()
|
||||
|
||||
#
|
||||
# Replace the content of this word with another one. Concurrent replacements are not merged!
|
||||
@@ -133,7 +142,7 @@ module.exports = (HB)->
|
||||
@saveOperation 'replace_manager', op
|
||||
@validateSavedOperations
|
||||
|
||||
toJson: ()->
|
||||
_encode: ()->
|
||||
json = {
|
||||
'type': "Word"
|
||||
'uid' : @getUid()
|
||||
@@ -162,7 +171,6 @@ module.exports = (HB)->
|
||||
types['TextInsert'] = TextInsert
|
||||
types['TextDelete'] = TextDelete
|
||||
types['Word'] = Word
|
||||
|
||||
structured_types
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user