observer will get the reference too now (ListManager)

This commit is contained in:
Kevin Jahns 2015-04-23 15:27:20 +02:00
parent 7f6592a6b7
commit 6fc33e40bb
12 changed files with 53679 additions and 4 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,71 @@
var ConnectorClass, adaptConnector;
ConnectorClass = require("./ConnectorClass");
adaptConnector = function(connector, engine, HB, execution_listener) {
var applyHB, encode_state_vector, f, getHB, getStateVector, name, parse_state_vector, send_;
for (name in ConnectorClass) {
f = ConnectorClass[name];
connector[name] = f;
}
connector.setIsBoundToY();
send_ = function(o) {
if ((o.uid.creator === HB.getUserId()) && (typeof o.uid.op_number !== "string") && (HB.getUserId() !== "_temp")) {
return connector.broadcast(o);
}
};
if (connector.invokeSync != null) {
HB.setInvokeSyncHandler(connector.invokeSync);
}
execution_listener.push(send_);
encode_state_vector = function(v) {
var results, value;
results = [];
for (name in v) {
value = v[name];
results.push({
user: name,
state: value
});
}
return results;
};
parse_state_vector = function(v) {
var i, len, s, state_vector;
state_vector = {};
for (i = 0, len = v.length; i < len; i++) {
s = v[i];
state_vector[s.user] = s.state;
}
return state_vector;
};
getStateVector = function() {
return encode_state_vector(HB.getOperationCounter());
};
getHB = function(v) {
var hb, json, state_vector;
state_vector = parse_state_vector(v);
hb = HB._encode(state_vector);
json = {
hb: hb,
state_vector: encode_state_vector(HB.getOperationCounter())
};
return json;
};
applyHB = function(hb, fromHB) {
return engine.applyOp(hb, fromHB);
};
connector.getStateVector = getStateVector;
connector.getHB = getHB;
connector.applyHB = applyHB;
if (connector.receive_handlers == null) {
connector.receive_handlers = [];
}
return connector.receive_handlers.push(function(sender, op) {
if (op.uid.creator !== HB.getUserId()) {
return engine.applyOp(op);
}
});
};
module.exports = adaptConnector;

261
build/node/HistoryBuffer.js Normal file
View File

@ -0,0 +1,261 @@
var HistoryBuffer,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
HistoryBuffer = (function() {
function HistoryBuffer(user_id1) {
this.user_id = user_id1;
this.emptyGarbage = bind(this.emptyGarbage, this);
this.operation_counter = {};
this.buffer = {};
this.change_listeners = [];
this.garbage = [];
this.trash = [];
this.performGarbageCollection = true;
this.garbageCollectTimeout = 30000;
this.reserved_identifier_counter = 0;
setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
}
HistoryBuffer.prototype.resetUserId = function(id) {
var o, o_name, own;
own = this.buffer[this.user_id];
if (own != null) {
for (o_name in own) {
o = own[o_name];
if (o.uid.creator != null) {
o.uid.creator = id;
}
if (o.uid.alt != null) {
o.uid.alt.creator = id;
}
}
if (this.buffer[id] != null) {
throw new Error("You are re-assigning an old user id - this is not (yet) possible!");
}
this.buffer[id] = own;
delete this.buffer[this.user_id];
}
if (this.operation_counter[this.user_id] != null) {
this.operation_counter[id] = this.operation_counter[this.user_id];
delete this.operation_counter[this.user_id];
}
return this.user_id = id;
};
HistoryBuffer.prototype.emptyGarbage = function() {
var i, len, o, ref;
ref = this.garbage;
for (i = 0, len = ref.length; i < len; i++) {
o = ref[i];
if (typeof o.cleanup === "function") {
o.cleanup();
}
}
this.garbage = this.trash;
this.trash = [];
if (this.garbageCollectTimeout !== -1) {
this.garbageCollectTimeoutId = setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
}
return void 0;
};
HistoryBuffer.prototype.getUserId = function() {
return this.user_id;
};
HistoryBuffer.prototype.addToGarbageCollector = function() {
var i, len, o, results;
if (this.performGarbageCollection) {
results = [];
for (i = 0, len = arguments.length; i < len; i++) {
o = arguments[i];
if (o != null) {
results.push(this.garbage.push(o));
} else {
results.push(void 0);
}
}
return results;
}
};
HistoryBuffer.prototype.stopGarbageCollection = function() {
this.performGarbageCollection = false;
this.setManualGarbageCollect();
this.garbage = [];
return this.trash = [];
};
HistoryBuffer.prototype.setManualGarbageCollect = function() {
this.garbageCollectTimeout = -1;
clearTimeout(this.garbageCollectTimeoutId);
return this.garbageCollectTimeoutId = void 0;
};
HistoryBuffer.prototype.setGarbageCollectTimeout = function(garbageCollectTimeout) {
this.garbageCollectTimeout = garbageCollectTimeout;
};
HistoryBuffer.prototype.getReservedUniqueIdentifier = function() {
return {
creator: '_',
op_number: "_" + (this.reserved_identifier_counter++)
};
};
HistoryBuffer.prototype.getOperationCounter = function(user_id) {
var ctn, ref, res, user;
if (user_id == null) {
res = {};
ref = this.operation_counter;
for (user in ref) {
ctn = ref[user];
res[user] = ctn;
}
return res;
} else {
return this.operation_counter[user_id];
}
};
HistoryBuffer.prototype.isExpectedOperation = function(o) {
var base, name;
if ((base = this.operation_counter)[name = o.uid.creator] == null) {
base[name] = 0;
}
o.uid.op_number <= this.operation_counter[o.uid.creator];
return true;
};
HistoryBuffer.prototype._encode = function(state_vector) {
var json, o, o_json, o_next, o_number, o_prev, ref, u_name, unknown, user;
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];
if (u_name === "_") {
continue;
}
for (o_number in user) {
o = user[o_number];
if ((o.uid.noOperation == null) && 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.uid.creator, o_next.uid.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_prev.uid.creator, o_prev.uid.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 o, ref;
if (uid.uid != null) {
uid = uid.uid;
}
o = (ref = this.buffer[uid.creator]) != null ? ref[uid.op_number] : void 0;
if ((uid.sub != null) && (o != null)) {
return o.retrieveSub(uid.sub);
} else {
return o;
}
};
HistoryBuffer.prototype.addOperation = function(o) {
if (this.buffer[o.uid.creator] == null) {
this.buffer[o.uid.creator] = {};
}
if (this.buffer[o.uid.creator][o.uid.op_number] != null) {
throw new Error("You must not overwrite operations!");
}
if ((o.uid.op_number.constructor !== String) && (!this.isExpectedOperation(o)) && (o.fromHB == null)) {
throw new Error("this operation was not expected!");
}
this.addToCounter(o);
this.buffer[o.uid.creator][o.uid.op_number] = o;
return o;
};
HistoryBuffer.prototype.removeOperation = function(o) {
var ref;
return (ref = this.buffer[o.uid.creator]) != null ? delete ref[o.uid.op_number] : void 0;
};
HistoryBuffer.prototype.setInvokeSyncHandler = function(f) {
return this.invokeSync = f;
};
HistoryBuffer.prototype.invokeSync = function() {};
HistoryBuffer.prototype.renewStateVector = function(state_vector) {
var results, state, user;
results = [];
for (user in state_vector) {
state = state_vector[user];
if (((this.operation_counter[user] == null) || (this.operation_counter[user] < state_vector[user])) && (state_vector[user] != null)) {
results.push(this.operation_counter[user] = state_vector[user]);
} else {
results.push(void 0);
}
}
return results;
};
HistoryBuffer.prototype.addToCounter = function(o) {
var base, name;
if ((base = this.operation_counter)[name = o.uid.creator] == null) {
base[name] = 0;
}
if (o.uid.creator !== this.getUserId()) {
if (o.uid.op_number === this.operation_counter[o.uid.creator]) {
this.operation_counter[o.uid.creator]++;
}
while (this.buffer[o.uid.creator][this.operation_counter[o.uid.creator]] != null) {
this.operation_counter[o.uid.creator]++;
}
return void 0;
}
};
return HistoryBuffer;
})();
module.exports = HistoryBuffer;

View File

@ -0,0 +1,663 @@
var slice = [].slice,
extend = 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; },
hasProp = {}.hasOwnProperty;
module.exports = function() {
var execution_listener, ops;
ops = {};
execution_listener = [];
ops.Operation = (function() {
function Operation(custom_type, uid, content, content_operations) {
var name, op;
if (custom_type != null) {
this.custom_type = custom_type;
}
this.is_deleted = false;
this.garbage_collected = false;
this.event_listeners = [];
if (uid != null) {
this.uid = uid;
}
if (content === void 0) {
} else if ((content != null) && (content.creator != null)) {
this.saveOperation('content', content);
} else {
this.content = content;
}
if (content_operations != null) {
this.content_operations = {};
for (name in content_operations) {
op = content_operations[name];
this.saveOperation(name, op, 'content_operations');
}
}
}
Operation.prototype.type = "Operation";
Operation.prototype.getContent = function(name) {
var content, n, ref, ref1, v;
if (this.content != null) {
if (this.content.getCustomType != null) {
return this.content.getCustomType();
} else if (this.content.constructor === Object) {
if (name != null) {
if (this.content[name] != null) {
return this.content[name];
} else {
return this.content_operations[name].getCustomType();
}
} else {
content = {};
ref = this.content;
for (n in ref) {
v = ref[n];
content[n] = v;
}
if (this.content_operations != null) {
ref1 = this.content_operations;
for (n in ref1) {
v = ref1[n];
v = v.getCustomType();
content[n] = v;
}
}
return content;
}
} else {
return this.content;
}
} else {
return this.content;
}
};
Operation.prototype.retrieveSub = function() {
throw new Error("sub properties are not enable on this operation type!");
};
Operation.prototype.observe = function(f) {
return this.event_listeners.push(f);
};
Operation.prototype.unobserve = function(f) {
return this.event_listeners = this.event_listeners.filter(function(g) {
return f !== g;
});
};
Operation.prototype.deleteAllObservers = function() {
return this.event_listeners = [];
};
Operation.prototype["delete"] = function() {
(new ops.Delete(void 0, this)).execute();
return null;
};
Operation.prototype.callEvent = function() {
var callon;
if (this.custom_type != null) {
callon = this.getCustomType();
} else {
callon = this;
}
return this.forwardEvent.apply(this, [callon].concat(slice.call(arguments)));
};
Operation.prototype.forwardEvent = function() {
var args, f, j, len, op, ref, results;
op = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
ref = this.event_listeners;
results = [];
for (j = 0, len = ref.length; j < len; j++) {
f = ref[j];
results.push(f.call.apply(f, [op].concat(slice.call(args))));
}
return results;
};
Operation.prototype.isDeleted = function() {
return this.is_deleted;
};
Operation.prototype.applyDelete = function(garbagecollect) {
if (garbagecollect == null) {
garbagecollect = true;
}
if (!this.garbage_collected) {
this.is_deleted = true;
if (garbagecollect) {
this.garbage_collected = true;
return this.HB.addToGarbageCollector(this);
}
}
};
Operation.prototype.cleanup = function() {
this.HB.removeOperation(this);
return this.deleteAllObservers();
};
Operation.prototype.setParent = function(parent1) {
this.parent = parent1;
};
Operation.prototype.getParent = function() {
return this.parent;
};
Operation.prototype.getUid = function() {
var map_uid;
if (this.uid.noOperation == null) {
return this.uid;
} else {
if (this.uid.alt != null) {
map_uid = this.uid.alt.cloneUid();
map_uid.sub = this.uid.sub;
return map_uid;
} else {
return void 0;
}
}
};
Operation.prototype.cloneUid = function() {
var n, ref, uid, v;
uid = {};
ref = this.getUid();
for (n in ref) {
v = ref[n];
uid[n] = v;
}
return uid;
};
Operation.prototype.execute = function() {
var j, l, len;
if (this.validateSavedOperations()) {
this.is_executed = true;
if (this.uid == null) {
this.uid = this.HB.getNextOperationIdentifier();
}
if (this.uid.noOperation == null) {
this.HB.addOperation(this);
for (j = 0, len = execution_listener.length; j < len; j++) {
l = execution_listener[j];
l(this._encode());
}
}
return this;
} else {
return false;
}
};
Operation.prototype.saveOperation = function(name, op, base) {
var base1, dest, j, last_path, len, path, paths;
if (base == null) {
base = "this";
}
if ((op != null) && (op._getModel != null)) {
op = op._getModel(this.custom_types, this.operations);
}
if (op == null) {
} else if ((op.execute != null) || !((op.op_number != null) && (op.creator != null))) {
if (base === "this") {
return this[name] = op;
} else {
dest = this[base];
paths = name.split("/");
last_path = paths.pop();
for (j = 0, len = paths.length; j < len; j++) {
path = paths[j];
dest = dest[path];
}
return dest[last_path] = op;
}
} else {
if (this.unchecked == null) {
this.unchecked = {};
}
if ((base1 = this.unchecked)[base] == null) {
base1[base] = {};
}
return this.unchecked[base][name] = op;
}
};
Operation.prototype.validateSavedOperations = function() {
var base, base_name, dest, j, last_path, len, name, op, op_uid, path, paths, ref, success, uninstantiated;
uninstantiated = {};
success = true;
ref = this.unchecked;
for (base_name in ref) {
base = ref[base_name];
for (name in base) {
op_uid = base[name];
op = this.HB.getOperation(op_uid);
if (op) {
if (base_name === "this") {
this[name] = op;
} else {
dest = this[base_name];
paths = name.split("/");
last_path = paths.pop();
for (j = 0, len = paths.length; j < len; j++) {
path = paths[j];
dest = dest[path];
}
dest[last_path] = op;
}
} else {
if (uninstantiated[base_name] == null) {
uninstantiated[base_name] = {};
}
uninstantiated[base_name][name] = op_uid;
success = false;
}
}
}
if (!success) {
this.unchecked = uninstantiated;
return false;
} else {
delete this.unchecked;
return this;
}
};
Operation.prototype.getCustomType = function() {
var Type, j, len, ref, t;
if (this.custom_type == null) {
return this;
} else {
if (this.custom_type.constructor === String) {
Type = this.custom_types;
ref = this.custom_type.split(".");
for (j = 0, len = ref.length; j < len; j++) {
t = ref[j];
Type = Type[t];
}
this.custom_type = new Type();
this.custom_type._setModel(this);
}
return this.custom_type;
}
};
Operation.prototype._encode = function(json) {
var n, o, operations, ref, ref1;
if (json == null) {
json = {};
}
json.type = this.type;
json.uid = this.getUid();
if (this.custom_type != null) {
if (this.custom_type.constructor === String) {
json.custom_type = this.custom_type;
} else {
json.custom_type = this.custom_type._name;
}
}
if (((ref = this.content) != null ? ref.getUid : void 0) != null) {
json.content = this.content.getUid();
} else {
json.content = this.content;
}
if (this.content_operations != null) {
operations = {};
ref1 = this.content_operations;
for (n in ref1) {
o = ref1[n];
if (o._getModel != null) {
o = o._getModel(this.custom_types, this.operations);
}
operations[n] = o.getUid();
}
json.content_operations = operations;
}
return json;
};
return Operation;
})();
ops.Delete = (function(superClass) {
extend(Delete, superClass);
function Delete(custom_type, uid, deletes) {
this.saveOperation('deletes', deletes);
Delete.__super__.constructor.call(this, custom_type, uid);
}
Delete.prototype.type = "Delete";
Delete.prototype._encode = function() {
return {
'type': "Delete",
'uid': this.getUid(),
'deletes': this.deletes.getUid()
};
};
Delete.prototype.execute = function() {
var res;
if (this.validateSavedOperations()) {
res = Delete.__super__.execute.apply(this, arguments);
if (res) {
this.deletes.applyDelete(this);
}
return res;
} else {
return false;
}
};
return Delete;
})(ops.Operation);
ops.Delete.parse = function(o) {
var deletes_uid, uid;
uid = o['uid'], deletes_uid = o['deletes'];
return new this(null, uid, deletes_uid);
};
ops.Insert = (function(superClass) {
extend(Insert, superClass);
function Insert(custom_type, content, content_operations, parent, uid, prev_cl, next_cl, origin) {
this.saveOperation('parent', parent);
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, custom_type, uid, content, content_operations);
}
Insert.prototype.type = "Insert";
Insert.prototype.val = function() {
return this.getContent();
};
Insert.prototype.getNext = function(i) {
var n;
if (i == null) {
i = 1;
}
n = this;
while (i > 0 && n.is_deleted && (n.next_cl != null)) {
n = n.next_cl;
if (!n.is_deleted) {
i--;
}
}
return n;
};
Insert.prototype.getPrev = function(i) {
var n;
if (i == null) {
i = 1;
}
n = this;
while (i > 0 && n.is_deleted && (n.prev_cl != null)) {
n = n.prev_cl;
if (!n.is_deleted) {
i--;
}
}
return n;
};
Insert.prototype.applyDelete = function(o) {
var callLater, garbagecollect, ref;
if (this.deleted_by == null) {
this.deleted_by = [];
}
callLater = false;
if ((this.parent != null) && !this.is_deleted && (o != null)) {
callLater = true;
}
if (o != null) {
this.deleted_by.push(o);
}
garbagecollect = false;
if (this.next_cl.isDeleted()) {
garbagecollect = true;
}
Insert.__super__.applyDelete.call(this, garbagecollect);
if (callLater) {
this.parent.callOperationSpecificDeleteEvents(this, o);
}
if ((ref = this.prev_cl) != null ? ref.isDeleted() : void 0) {
return this.prev_cl.applyDelete();
}
};
Insert.prototype.cleanup = function() {
var d, j, len, o, ref;
if (this.next_cl.isDeleted()) {
ref = this.deleted_by;
for (j = 0, len = ref.length; j < len; j++) {
d = ref[j];
d.cleanup();
}
o = this.next_cl;
while (o.type !== "Delimiter") {
if (o.origin === this) {
o.origin = this.prev_cl;
}
o = o.next_cl;
}
this.prev_cl.next_cl = this.next_cl;
this.next_cl.prev_cl = this.prev_cl;
if (this.content instanceof ops.Operation) {
this.content.referenced_by--;
if (this.content.referenced_by <= 0 && !this.content.is_deleted) {
this.content.applyDelete();
}
}
delete this.content;
return Insert.__super__.cleanup.apply(this, arguments);
}
};
Insert.prototype.getDistanceToOrigin = function() {
var d, o;
d = 0;
o = this.prev_cl;
while (true) {
if (this.origin === o) {
break;
}
d++;
o = o.prev_cl;
}
return d;
};
Insert.prototype.execute = function() {
var base1, distance_to_origin, i, o;
if (!this.validateSavedOperations()) {
return false;
} else {
if (this.content instanceof ops.Operation) {
this.content.insert_parent = this;
if ((base1 = this.content).referenced_by == null) {
base1.referenced_by = 0;
}
this.content.referenced_by++;
}
if (this.parent != null) {
if (this.prev_cl == null) {
this.prev_cl = this.parent.beginning;
}
if (this.origin == null) {
this.origin = this.prev_cl;
} else if (this.origin === "Delimiter") {
this.origin = this.parent.beginning;
}
if (this.next_cl == null) {
this.next_cl = this.parent.end;
}
}
if (this.prev_cl != null) {
distance_to_origin = this.getDistanceToOrigin();
o = this.prev_cl.next_cl;
i = distance_to_origin;
while (true) {
if (o !== this.next_cl) {
if (o.getDistanceToOrigin() === i) {
if (o.uid.creator < this.uid.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;
}
this.setParent(this.prev_cl.getParent());
Insert.__super__.execute.apply(this, arguments);
this.parent.callOperationSpecificInsertEvents(this);
return this;
}
};
Insert.prototype.getPosition = function() {
var position, prev;
position = 0;
prev = this.prev_cl;
while (true) {
if (prev instanceof ops.Delimiter) {
break;
}
if (!prev.isDeleted()) {
position++;
}
prev = prev.prev_cl;
}
return position;
};
Insert.prototype._encode = function(json) {
if (json == null) {
json = {};
}
json.prev = this.prev_cl.getUid();
json.next = this.next_cl.getUid();
if (this.origin.type === "Delimiter") {
json.origin = "Delimiter";
} else if (this.origin !== this.prev_cl) {
json.origin = this.origin.getUid();
}
json.parent = this.parent.getUid();
return Insert.__super__._encode.call(this, json);
};
return Insert;
})(ops.Operation);
ops.Insert.parse = function(json) {
var content, content_operations, next, origin, parent, prev, uid;
content = json['content'], content_operations = json['content_operations'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], parent = json['parent'];
return new this(null, content, content_operations, parent, uid, prev, next, origin);
};
ops.Delimiter = (function(superClass) {
extend(Delimiter, superClass);
function Delimiter(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, null, {
noOperation: true
});
}
Delimiter.prototype.type = "Delimiter";
Delimiter.prototype.applyDelete = function() {
var o;
Delimiter.__super__.applyDelete.call(this);
o = this.prev_cl;
while (o != null) {
o.applyDelete();
o = o.prev_cl;
}
return void 0;
};
Delimiter.prototype.cleanup = function() {
return Delimiter.__super__.cleanup.call(this);
};
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;
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;
this.prev_cl.next_cl = this;
return Delimiter.__super__.execute.apply(this, arguments);
} else if ((this.prev_cl != null) || (this.next_cl != null) || true) {
return Delimiter.__super__.execute.apply(this, arguments);
}
};
Delimiter.prototype._encode = function() {
var ref, ref1;
return {
'type': this.type,
'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;
})(ops.Operation);
ops.Delimiter.parse = function(json) {
var next, prev, uid;
uid = json['uid'], prev = json['prev'], next = json['next'];
return new this(uid, prev, next);
};
return {
'operations': ops,
'execution_listener': execution_listener
};
};

View File

@ -334,6 +334,7 @@ module.exports = function() {
return this.callEvent([
{
type: "insert",
reference: op,
position: op.getPosition(),
object: this.getCustomType(),
changedBy: op.uid.creator,
@ -346,6 +347,7 @@ module.exports = function() {
return this.callEvent([
{
type: "delete",
reference: op,
position: op.getPosition(),
object: this.getCustomType(),
length: 1,

92
build/node/y-object.js Normal file
View File

@ -0,0 +1,92 @@
var Y, bindToChildren;
Y = require('./y');
bindToChildren = function(that) {
var attr, i, j, ref;
for (i = j = 0, ref = that.children.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
attr = that.children.item(i);
if (attr.name != null) {
attr.val = that.val.val(attr.name);
}
}
return that.val.observe(function(events) {
var event, k, len, newVal, results;
results = [];
for (k = 0, len = events.length; k < len; k++) {
event = events[k];
if (event.name != null) {
results.push((function() {
var l, ref1, results1;
results1 = [];
for (i = l = 0, ref1 = that.children.length; 0 <= ref1 ? l < ref1 : l > ref1; i = 0 <= ref1 ? ++l : --l) {
attr = that.children.item(i);
if ((attr.name != null) && attr.name === event.name) {
newVal = that.val.val(attr.name);
if (attr.val !== newVal) {
results1.push(attr.val = newVal);
} else {
results1.push(void 0);
}
} else {
results1.push(void 0);
}
}
return results1;
})());
} else {
results.push(void 0);
}
}
return results;
});
};
Polymer("y-object", {
ready: function() {
if (this.connector != null) {
this.val = new Y(this.connector);
return bindToChildren(this);
} else if (this.val != null) {
return bindToChildren(this);
}
},
valChanged: function() {
if ((this.val != null) && this.val.type === "Object") {
return bindToChildren(this);
}
},
connectorChanged: function() {
if (this.val == null) {
this.val = new Y(this.connector);
return bindToChildren(this);
}
}
});
Polymer("y-property", {
ready: function() {
if ((this.val != null) && (this.name != null)) {
if (this.val.constructor === Object) {
this.val = this.parentElement.val(this.name, this.val).val(this.name);
} else if (typeof this.val === "string") {
this.parentElement.val(this.name, this.val);
}
if (this.val.type === "Object") {
return bindToChildren(this);
}
}
},
valChanged: function() {
var ref;
if ((this.val != null) && (this.name != null)) {
if (this.val.constructor === Object) {
return this.val = this.parentElement.val.val(this.name, this.val).val(this.name);
} else if (this.val.type === "Object") {
return bindToChildren(this);
} else if ((((ref = this.parentElement.val) != null ? ref.val : void 0) != null) && this.val !== this.parentElement.val.val(this.name)) {
return this.parentElement.val.val(this.name, this.val);
}
}
}
});

32535
build/test/richtext-test.js Normal file

File diff suppressed because one or more lines are too long

20045
build/test/selections-test.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -289,6 +289,7 @@ module.exports = ()->
content
@callEvent [
type: "insert"
reference: op
position: op.getPosition()
object: @getCustomType()
changedBy: op.uid.creator
@ -298,6 +299,7 @@ module.exports = ()->
callOperationSpecificDeleteEvents: (op, del_op)->
@callEvent [
type: "delete"
reference: op
position: op.getPosition()
object: @getCustomType() # TODO: You can combine getPosition + getParent in a more efficient manner! (only left Delimiter will hold @parent)
length: 1

File diff suppressed because one or more lines are too long

2
y.js

File diff suppressed because one or more lines are too long