devided ops/types
This commit is contained in:
542
build/node/Operations/Basic.js
Normal file
542
build/node/Operations/Basic.js
Normal file
@@ -0,0 +1,542 @@
|
||||
var __slice = [].slice,
|
||||
__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; },
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
|
||||
module.exports = function() {
|
||||
var execution_listener, ops;
|
||||
ops = {};
|
||||
execution_listener = [];
|
||||
ops.Operation = (function() {
|
||||
function Operation(uid) {
|
||||
this.is_deleted = false;
|
||||
this.garbage_collected = false;
|
||||
this.event_listeners = [];
|
||||
if (uid != null) {
|
||||
this.uid = uid;
|
||||
}
|
||||
}
|
||||
|
||||
Operation.prototype.type = "Operation";
|
||||
|
||||
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() {
|
||||
return this.forwardEvent.apply(this, [this].concat(__slice.call(arguments)));
|
||||
};
|
||||
|
||||
Operation.prototype.forwardEvent = function() {
|
||||
var args, f, op, _i, _len, _ref, _results;
|
||||
op = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||||
_ref = this.event_listeners;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
f = _ref[_i];
|
||||
_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(_at_parent) {
|
||||
this.parent = _at_parent;
|
||||
};
|
||||
|
||||
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, uid, v, _ref;
|
||||
uid = {};
|
||||
_ref = this.getUid();
|
||||
for (n in _ref) {
|
||||
v = _ref[n];
|
||||
uid[n] = v;
|
||||
}
|
||||
return uid;
|
||||
};
|
||||
|
||||
Operation.prototype.execute = function() {
|
||||
var l, _i, _len;
|
||||
this.is_executed = true;
|
||||
if (this.uid == null) {
|
||||
this.uid = this.HB.getNextOperationIdentifier();
|
||||
}
|
||||
if (this.uid.noOperation == null) {
|
||||
this.HB.addOperation(this);
|
||||
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) {
|
||||
|
||||
} else if ((op.execute != null) || !((op.op_number != null) && (op.creator != null))) {
|
||||
return this[name] = op;
|
||||
} else {
|
||||
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 = this.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;
|
||||
|
||||
})();
|
||||
ops.Delete = (function(_super) {
|
||||
__extends(Delete, _super);
|
||||
|
||||
function Delete(uid, deletes) {
|
||||
this.saveOperation('deletes', deletes);
|
||||
Delete.__super__.constructor.call(this, 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(uid, deletes_uid);
|
||||
};
|
||||
ops.Insert = (function(_super) {
|
||||
__extends(Insert, _super);
|
||||
|
||||
function Insert(content, uid, prev_cl, next_cl, origin, parent) {
|
||||
if (content === void 0) {
|
||||
|
||||
} else if ((content != null) && (content.creator != null)) {
|
||||
this.saveOperation('content', content);
|
||||
} else {
|
||||
this.content = content;
|
||||
}
|
||||
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, uid);
|
||||
}
|
||||
|
||||
Insert.prototype.type = "Insert";
|
||||
|
||||
Insert.prototype.val = function() {
|
||||
return this.content;
|
||||
};
|
||||
|
||||
Insert.prototype.applyDelete = function(o) {
|
||||
var callLater, garbagecollect, _ref;
|
||||
if (this.deleted_by == null) {
|
||||
this.deleted_by = [];
|
||||
}
|
||||
callLater = false;
|
||||
if ((this.parent != null) && !this.isDeleted() && (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.callOperationSpecificDeleteEvents(o);
|
||||
}
|
||||
if ((_ref = this.prev_cl) != null ? _ref.isDeleted() : void 0) {
|
||||
this.prev_cl.applyDelete();
|
||||
}
|
||||
if (this.content instanceof ops.Operation) {
|
||||
this.content.applyDelete();
|
||||
}
|
||||
return delete this.content;
|
||||
};
|
||||
|
||||
Insert.prototype.cleanup = function() {
|
||||
var d, o, _i, _len, _ref;
|
||||
if (this.next_cl.isDeleted()) {
|
||||
_ref = this.deleted_by;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
d = _ref[_i];
|
||||
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;
|
||||
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 distance_to_origin, i, o;
|
||||
if (!this.validateSavedOperations()) {
|
||||
return false;
|
||||
} else {
|
||||
if (this.content instanceof ops.Operation) {
|
||||
this.content.insert_parent = this;
|
||||
}
|
||||
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.callOperationSpecificInsertEvents();
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
Insert.prototype.callOperationSpecificInsertEvents = function() {
|
||||
var _ref;
|
||||
return (_ref = this.parent) != null ? _ref.callEvent([
|
||||
{
|
||||
type: "insert",
|
||||
position: this.getPosition(),
|
||||
object: this.parent,
|
||||
changedBy: this.uid.creator,
|
||||
value: this.content
|
||||
}
|
||||
]) : void 0;
|
||||
};
|
||||
|
||||
Insert.prototype.callOperationSpecificDeleteEvents = function(o) {
|
||||
return this.parent.callEvent([
|
||||
{
|
||||
type: "delete",
|
||||
position: this.getPosition(),
|
||||
object: this.parent,
|
||||
length: 1,
|
||||
changedBy: o.uid.creator
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
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() {
|
||||
var json, _ref;
|
||||
json = {
|
||||
'type': this.type,
|
||||
'uid': this.getUid(),
|
||||
'prev': this.prev_cl.getUid(),
|
||||
'next': this.next_cl.getUid(),
|
||||
'parent': this.parent.getUid()
|
||||
};
|
||||
if (this.origin.type === "Delimiter") {
|
||||
json.origin = "Delimiter";
|
||||
} else if (this.origin !== this.prev_cl) {
|
||||
json.origin = this.origin.getUid();
|
||||
}
|
||||
if (((_ref = this.content) != null ? _ref.getUid : void 0) != null) {
|
||||
json['content'] = this.content.getUid();
|
||||
} else {
|
||||
json['content'] = JSON.stringify(this.content);
|
||||
}
|
||||
return json;
|
||||
};
|
||||
|
||||
return Insert;
|
||||
|
||||
})(ops.Operation);
|
||||
ops.Insert.parse = function(json) {
|
||||
var content, next, origin, parent, prev, uid;
|
||||
content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], parent = json['parent'];
|
||||
if (typeof content === "string") {
|
||||
content = JSON.parse(content);
|
||||
}
|
||||
return new this(content, uid, prev, next, origin, parent);
|
||||
};
|
||||
ops.ImmutableObject = (function(_super) {
|
||||
__extends(ImmutableObject, _super);
|
||||
|
||||
function ImmutableObject(uid, _at_content) {
|
||||
this.content = _at_content;
|
||||
ImmutableObject.__super__.constructor.call(this, uid);
|
||||
}
|
||||
|
||||
ImmutableObject.prototype.type = "ImmutableObject";
|
||||
|
||||
ImmutableObject.prototype.val = function() {
|
||||
return this.content;
|
||||
};
|
||||
|
||||
ImmutableObject.prototype._encode = function() {
|
||||
var json;
|
||||
json = {
|
||||
'type': this.type,
|
||||
'uid': this.getUid(),
|
||||
'content': this.content
|
||||
};
|
||||
return json;
|
||||
};
|
||||
|
||||
return ImmutableObject;
|
||||
|
||||
})(ops.Operation);
|
||||
ops.ImmutableObject.parse = function(json) {
|
||||
var content, uid;
|
||||
uid = json['uid'], content = json['content'];
|
||||
return new this(uid, content);
|
||||
};
|
||||
ops.Delimiter = (function(_super) {
|
||||
__extends(Delimiter, _super);
|
||||
|
||||
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, {
|
||||
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
|
||||
};
|
||||
};
|
||||
158
build/node/Operations/Json.js
Normal file
158
build/node/Operations/Json.js
Normal file
@@ -0,0 +1,158 @@
|
||||
var text_ops_uninitialized,
|
||||
__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; },
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
|
||||
text_ops_uninitialized = require("./Text");
|
||||
|
||||
module.exports = function() {
|
||||
var ops, text_ops;
|
||||
text_ops = text_ops_uninitialized();
|
||||
ops = text_ops.operations;
|
||||
ops.Object = (function(_super) {
|
||||
__extends(Object, _super);
|
||||
|
||||
function Object() {
|
||||
return Object.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Object.prototype.type = "Object";
|
||||
|
||||
Object.prototype.applyDelete = function() {
|
||||
return Object.__super__.applyDelete.call(this);
|
||||
};
|
||||
|
||||
Object.prototype.cleanup = function() {
|
||||
return Object.__super__.cleanup.call(this);
|
||||
};
|
||||
|
||||
Object.prototype.toJson = function(transform_to_value) {
|
||||
var json, name, o, that, val;
|
||||
if (transform_to_value == null) {
|
||||
transform_to_value = false;
|
||||
}
|
||||
if ((this.bound_json == null) || (Object.observe == null) || true) {
|
||||
val = this.val();
|
||||
json = {};
|
||||
for (name in val) {
|
||||
o = val[name];
|
||||
if (o instanceof ops.Object) {
|
||||
json[name] = o.toJson(transform_to_value);
|
||||
} else if (o instanceof ops.ListManager) {
|
||||
json[name] = o.toJson(transform_to_value);
|
||||
} else if (transform_to_value && o instanceof ops.Operation) {
|
||||
json[name] = o.val();
|
||||
} else {
|
||||
json[name] = o;
|
||||
}
|
||||
}
|
||||
this.bound_json = json;
|
||||
if (Object.observe != null) {
|
||||
that = this;
|
||||
Object.observe(this.bound_json, function(events) {
|
||||
var event, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = events.length; _i < _len; _i++) {
|
||||
event = events[_i];
|
||||
if ((event.changedBy == null) && (event.type === "add" || (event.type = "update"))) {
|
||||
_results.push(that.val(event.name, event.object[event.name]));
|
||||
} else {
|
||||
_results.push(void 0);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
this.observe(function(events) {
|
||||
var event, notifier, oldVal, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = events.length; _i < _len; _i++) {
|
||||
event = events[_i];
|
||||
if (event.created_ !== this.HB.getUserId()) {
|
||||
notifier = Object.getNotifier(that.bound_json);
|
||||
oldVal = that.bound_json[event.name];
|
||||
if (oldVal != null) {
|
||||
notifier.performChange('update', function() {
|
||||
return that.bound_json[event.name] = that.val(event.name);
|
||||
}, that.bound_json);
|
||||
_results.push(notifier.notify({
|
||||
object: that.bound_json,
|
||||
type: 'update',
|
||||
name: event.name,
|
||||
oldValue: oldVal,
|
||||
changedBy: event.changedBy
|
||||
}));
|
||||
} else {
|
||||
notifier.performChange('add', function() {
|
||||
return that.bound_json[event.name] = that.val(event.name);
|
||||
}, that.bound_json);
|
||||
_results.push(notifier.notify({
|
||||
object: that.bound_json,
|
||||
type: 'add',
|
||||
name: event.name,
|
||||
oldValue: oldVal,
|
||||
changedBy: event.changedBy
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
_results.push(void 0);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
}
|
||||
}
|
||||
return this.bound_json;
|
||||
};
|
||||
|
||||
Object.prototype.val = function(name, content) {
|
||||
var args, i, o, type, _i, _ref;
|
||||
if ((name != null) && arguments.length > 1) {
|
||||
if ((content != null) && (content.constructor != null)) {
|
||||
type = ops[content.constructor.name];
|
||||
if ((type != null) && (type.create != null)) {
|
||||
args = [];
|
||||
for (i = _i = 1, _ref = arguments.length; 1 <= _ref ? _i < _ref : _i > _ref; i = 1 <= _ref ? ++_i : --_i) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
o = type.create.apply(null, args);
|
||||
return Object.__super__.val.call(this, name, o);
|
||||
} else {
|
||||
throw new Error("The " + content.constructor.name + "-type is not (yet) supported in Y.");
|
||||
}
|
||||
} else {
|
||||
return Object.__super__.val.call(this, name, content);
|
||||
}
|
||||
} else {
|
||||
return Object.__super__.val.call(this, name);
|
||||
}
|
||||
};
|
||||
|
||||
Object.prototype._encode = function() {
|
||||
return {
|
||||
'type': this.type,
|
||||
'uid': this.getUid()
|
||||
};
|
||||
};
|
||||
|
||||
return Object;
|
||||
|
||||
})(ops.MapManager);
|
||||
ops.Object.parse = function(json) {
|
||||
var uid;
|
||||
uid = json['uid'];
|
||||
return new this(uid);
|
||||
};
|
||||
ops.Object.create = function(content, mutable) {
|
||||
var json, n, o;
|
||||
json = new ops.Object().execute();
|
||||
for (n in content) {
|
||||
o = content[n];
|
||||
json.val(n, o, mutable);
|
||||
}
|
||||
return json;
|
||||
};
|
||||
ops.Number = {};
|
||||
ops.Number.create = function(content) {
|
||||
return content;
|
||||
};
|
||||
return text_ops;
|
||||
};
|
||||
517
build/node/Operations/Structured.js
Normal file
517
build/node/Operations/Structured.js
Normal file
@@ -0,0 +1,517 @@
|
||||
var basic_ops_uninitialized,
|
||||
__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; },
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
|
||||
basic_ops_uninitialized = require("./Basic");
|
||||
|
||||
module.exports = function() {
|
||||
var basic_ops, ops;
|
||||
basic_ops = basic_ops_uninitialized();
|
||||
ops = basic_ops.operations;
|
||||
ops.MapManager = (function(_super) {
|
||||
__extends(MapManager, _super);
|
||||
|
||||
function MapManager(uid) {
|
||||
this.map = {};
|
||||
MapManager.__super__.constructor.call(this, uid);
|
||||
}
|
||||
|
||||
MapManager.prototype.type = "MapManager";
|
||||
|
||||
MapManager.prototype.applyDelete = function() {
|
||||
var name, p, _ref;
|
||||
_ref = this.map;
|
||||
for (name in _ref) {
|
||||
p = _ref[name];
|
||||
p.applyDelete();
|
||||
}
|
||||
return MapManager.__super__.applyDelete.call(this);
|
||||
};
|
||||
|
||||
MapManager.prototype.cleanup = function() {
|
||||
return MapManager.__super__.cleanup.call(this);
|
||||
};
|
||||
|
||||
MapManager.prototype.val = function(name, content) {
|
||||
var o, prop, result, _ref;
|
||||
if (arguments.length > 1) {
|
||||
this.retrieveSub(name).replace(content);
|
||||
return this;
|
||||
} else if (name != null) {
|
||||
prop = this.map[name];
|
||||
if ((prop != null) && !prop.isContentDeleted()) {
|
||||
return prop.val();
|
||||
} else {
|
||||
return void 0;
|
||||
}
|
||||
} else {
|
||||
result = {};
|
||||
_ref = this.map;
|
||||
for (name in _ref) {
|
||||
o = _ref[name];
|
||||
if (!o.isContentDeleted()) {
|
||||
result[name] = o.val();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
MapManager.prototype["delete"] = function(name) {
|
||||
var _ref;
|
||||
if ((_ref = this.map[name]) != null) {
|
||||
_ref.deleteContent();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
MapManager.prototype.retrieveSub = function(property_name) {
|
||||
var event_properties, event_this, rm, rm_uid;
|
||||
if (this.map[property_name] == null) {
|
||||
event_properties = {
|
||||
name: property_name
|
||||
};
|
||||
event_this = this;
|
||||
rm_uid = {
|
||||
noOperation: true,
|
||||
sub: property_name,
|
||||
alt: this
|
||||
};
|
||||
rm = new ops.ReplaceManager(event_properties, event_this, rm_uid);
|
||||
this.map[property_name] = rm;
|
||||
rm.setParent(this, property_name);
|
||||
rm.execute();
|
||||
}
|
||||
return this.map[property_name];
|
||||
};
|
||||
|
||||
return MapManager;
|
||||
|
||||
})(ops.Operation);
|
||||
ops.ListManager = (function(_super) {
|
||||
__extends(ListManager, _super);
|
||||
|
||||
function ListManager(uid) {
|
||||
this.beginning = new ops.Delimiter(void 0, void 0);
|
||||
this.end = new ops.Delimiter(this.beginning, void 0);
|
||||
this.beginning.next_cl = this.end;
|
||||
this.beginning.execute();
|
||||
this.end.execute();
|
||||
ListManager.__super__.constructor.call(this, uid);
|
||||
}
|
||||
|
||||
ListManager.prototype.type = "ListManager";
|
||||
|
||||
ListManager.prototype.applyDelete = function() {
|
||||
var o;
|
||||
o = this.end;
|
||||
while (o != null) {
|
||||
o.applyDelete();
|
||||
o = o.prev_cl;
|
||||
}
|
||||
return ListManager.__super__.applyDelete.call(this);
|
||||
};
|
||||
|
||||
ListManager.prototype.cleanup = function() {
|
||||
return ListManager.__super__.cleanup.call(this);
|
||||
};
|
||||
|
||||
ListManager.prototype.toJson = function(transform_to_value) {
|
||||
var i, o, val, _i, _len, _results;
|
||||
if (transform_to_value == null) {
|
||||
transform_to_value = false;
|
||||
}
|
||||
val = this.val();
|
||||
_results = [];
|
||||
for (o = _i = 0, _len = val.length; _i < _len; o = ++_i) {
|
||||
i = val[o];
|
||||
if (o instanceof ops.Object) {
|
||||
_results.push(o.toJson(transform_to_value));
|
||||
} else if (o instanceof ops.ListManager) {
|
||||
_results.push(o.toJson(transform_to_value));
|
||||
} else if (transform_to_value && o instanceof ops.Operation) {
|
||||
_results.push(o.val());
|
||||
} else {
|
||||
_results.push(o);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
ListManager.prototype.execute = function() {
|
||||
if (this.validateSavedOperations()) {
|
||||
this.beginning.setParent(this);
|
||||
this.end.setParent(this);
|
||||
return ListManager.__super__.execute.apply(this, arguments);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
if (!o.is_deleted) {
|
||||
result.push(o);
|
||||
}
|
||||
o = o.next_cl;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
ListManager.prototype.map = function(f) {
|
||||
var o, result;
|
||||
o = this.beginning.next_cl;
|
||||
result = [];
|
||||
while (o !== this.end) {
|
||||
if (!o.is_deleted) {
|
||||
result.push(f(o));
|
||||
}
|
||||
o = o.next_cl;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
ListManager.prototype.fold = function(init, f) {
|
||||
var o;
|
||||
o = this.beginning.next_cl;
|
||||
while (o !== this.end) {
|
||||
if (!o.is_deleted) {
|
||||
init = f(init, o);
|
||||
}
|
||||
o = o.next_cl;
|
||||
}
|
||||
return init;
|
||||
};
|
||||
|
||||
ListManager.prototype.val = function(pos) {
|
||||
var o;
|
||||
if (pos != null) {
|
||||
o = this.getOperationByPosition(pos + 1);
|
||||
if (!(o instanceof ops.Delimiter)) {
|
||||
return o.val();
|
||||
} else {
|
||||
throw new Error("this position does not exist");
|
||||
}
|
||||
} else {
|
||||
return this.toArray();
|
||||
}
|
||||
};
|
||||
|
||||
ListManager.prototype.getOperationByPosition = function(position) {
|
||||
var o;
|
||||
o = this.beginning;
|
||||
while (true) {
|
||||
if (o instanceof ops.Delimiter && (o.prev_cl != null)) {
|
||||
o = o.prev_cl;
|
||||
while (o.isDeleted() && (o.prev_cl != null)) {
|
||||
o = o.prev_cl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (position <= 0 && !o.isDeleted()) {
|
||||
break;
|
||||
}
|
||||
o = o.next_cl;
|
||||
if (!o.isDeleted()) {
|
||||
position -= 1;
|
||||
}
|
||||
}
|
||||
return o;
|
||||
};
|
||||
|
||||
ListManager.prototype.push = function(content) {
|
||||
return this.insertAfter(this.end.prev_cl, content);
|
||||
};
|
||||
|
||||
ListManager.prototype.insertAfter = function(left, content, options) {
|
||||
var c, createContent, right, tmp, _i, _len;
|
||||
createContent = function(content, options) {
|
||||
var type;
|
||||
if ((content != null) && (content.constructor != null)) {
|
||||
type = ops[content.constructor.name];
|
||||
if ((type != null) && (type.create != null)) {
|
||||
return type.create(content, options);
|
||||
} else {
|
||||
throw new Error("The " + content.constructor.name + "-type is not (yet) supported in Y.");
|
||||
}
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
};
|
||||
right = left.next_cl;
|
||||
while (right.isDeleted()) {
|
||||
right = right.next_cl;
|
||||
}
|
||||
left = right.prev_cl;
|
||||
if (content instanceof ops.Operation) {
|
||||
(new ops.Insert(content, void 0, left, right)).execute();
|
||||
} else {
|
||||
for (_i = 0, _len = content.length; _i < _len; _i++) {
|
||||
c = content[_i];
|
||||
tmp = (new ops.Insert(createContent(c, options), void 0, left, right)).execute();
|
||||
left = tmp;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
ListManager.prototype.insert = function(position, content, options) {
|
||||
var ith;
|
||||
ith = this.getOperationByPosition(position);
|
||||
return this.insertAfter(ith, [content], options);
|
||||
};
|
||||
|
||||
ListManager.prototype["delete"] = function(position, length) {
|
||||
var d, delete_ops, i, o, _i;
|
||||
o = this.getOperationByPosition(position + 1);
|
||||
delete_ops = [];
|
||||
for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {
|
||||
if (o instanceof ops.Delimiter) {
|
||||
break;
|
||||
}
|
||||
d = (new ops.Delete(void 0, o)).execute();
|
||||
o = o.next_cl;
|
||||
while ((!(o instanceof ops.Delimiter)) && o.isDeleted()) {
|
||||
o = o.next_cl;
|
||||
}
|
||||
delete_ops.push(d._encode());
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
ListManager.prototype._encode = function() {
|
||||
var json;
|
||||
json = {
|
||||
'type': this.type,
|
||||
'uid': this.getUid()
|
||||
};
|
||||
return json;
|
||||
};
|
||||
|
||||
return ListManager;
|
||||
|
||||
})(ops.Operation);
|
||||
ops.ListManager.parse = function(json) {
|
||||
var uid;
|
||||
uid = json['uid'];
|
||||
return new this(uid);
|
||||
};
|
||||
ops.Array = function() {};
|
||||
ops.Array.create = function(content, mutable) {
|
||||
var ith, list;
|
||||
if (mutable === "mutable") {
|
||||
list = new ops.ListManager().execute();
|
||||
ith = list.getOperationByPosition(0);
|
||||
list.insertAfter(ith, content);
|
||||
return list;
|
||||
} else if ((mutable == null) || (mutable === "immutable")) {
|
||||
return content;
|
||||
} else {
|
||||
throw new Error("Specify either \"mutable\" or \"immutable\"!!");
|
||||
}
|
||||
};
|
||||
ops.ReplaceManager = (function(_super) {
|
||||
__extends(ReplaceManager, _super);
|
||||
|
||||
function ReplaceManager(_at_event_properties, _at_event_this, uid, beginning, end) {
|
||||
this.event_properties = _at_event_properties;
|
||||
this.event_this = _at_event_this;
|
||||
if (this.event_properties['object'] == null) {
|
||||
this.event_properties['object'] = this.event_this;
|
||||
}
|
||||
ReplaceManager.__super__.constructor.call(this, uid, beginning, end);
|
||||
}
|
||||
|
||||
ReplaceManager.prototype.type = "ReplaceManager";
|
||||
|
||||
ReplaceManager.prototype.applyDelete = function() {
|
||||
var o;
|
||||
o = this.beginning;
|
||||
while (o != null) {
|
||||
o.applyDelete();
|
||||
o = o.next_cl;
|
||||
}
|
||||
return ReplaceManager.__super__.applyDelete.call(this);
|
||||
};
|
||||
|
||||
ReplaceManager.prototype.cleanup = function() {
|
||||
return ReplaceManager.__super__.cleanup.call(this);
|
||||
};
|
||||
|
||||
ReplaceManager.prototype.callEventDecorator = function(events) {
|
||||
var event, name, prop, _i, _len, _ref;
|
||||
if (!this.isDeleted()) {
|
||||
for (_i = 0, _len = events.length; _i < _len; _i++) {
|
||||
event = events[_i];
|
||||
_ref = this.event_properties;
|
||||
for (name in _ref) {
|
||||
prop = _ref[name];
|
||||
event[name] = prop;
|
||||
}
|
||||
}
|
||||
this.event_this.callEvent(events);
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
ReplaceManager.prototype.replace = function(content, replaceable_uid) {
|
||||
var o, relp;
|
||||
o = this.getLastOperation();
|
||||
relp = (new ops.Replaceable(content, this, replaceable_uid, o, o.next_cl)).execute();
|
||||
return void 0;
|
||||
};
|
||||
|
||||
ReplaceManager.prototype.isContentDeleted = function() {
|
||||
return this.getLastOperation().isDeleted();
|
||||
};
|
||||
|
||||
ReplaceManager.prototype.deleteContent = function() {
|
||||
(new ops.Delete(void 0, this.getLastOperation().uid)).execute();
|
||||
return void 0;
|
||||
};
|
||||
|
||||
ReplaceManager.prototype.val = function() {
|
||||
var o;
|
||||
o = this.getLastOperation();
|
||||
return typeof o.val === "function" ? o.val() : void 0;
|
||||
};
|
||||
|
||||
ReplaceManager.prototype._encode = function() {
|
||||
var json;
|
||||
json = {
|
||||
'type': this.type,
|
||||
'uid': this.getUid(),
|
||||
'beginning': this.beginning.getUid(),
|
||||
'end': this.end.getUid()
|
||||
};
|
||||
return json;
|
||||
};
|
||||
|
||||
return ReplaceManager;
|
||||
|
||||
})(ops.ListManager);
|
||||
ops.Replaceable = (function(_super) {
|
||||
__extends(Replaceable, _super);
|
||||
|
||||
function Replaceable(content, parent, uid, prev, next, origin, is_deleted) {
|
||||
this.saveOperation('parent', parent);
|
||||
Replaceable.__super__.constructor.call(this, content, uid, prev, next, origin);
|
||||
this.is_deleted = is_deleted;
|
||||
}
|
||||
|
||||
Replaceable.prototype.type = "Replaceable";
|
||||
|
||||
Replaceable.prototype.val = function() {
|
||||
return this.content;
|
||||
};
|
||||
|
||||
Replaceable.prototype.applyDelete = function() {
|
||||
var res, _base, _base1, _base2;
|
||||
res = Replaceable.__super__.applyDelete.apply(this, arguments);
|
||||
if (this.content != null) {
|
||||
if (this.next_cl.type !== "Delimiter") {
|
||||
if (typeof (_base = this.content).deleteAllObservers === "function") {
|
||||
_base.deleteAllObservers();
|
||||
}
|
||||
}
|
||||
if (typeof (_base1 = this.content).applyDelete === "function") {
|
||||
_base1.applyDelete();
|
||||
}
|
||||
if (typeof (_base2 = this.content).dontSync === "function") {
|
||||
_base2.dontSync();
|
||||
}
|
||||
}
|
||||
this.content = null;
|
||||
return res;
|
||||
};
|
||||
|
||||
Replaceable.prototype.cleanup = function() {
|
||||
return Replaceable.__super__.cleanup.apply(this, arguments);
|
||||
};
|
||||
|
||||
Replaceable.prototype.callOperationSpecificInsertEvents = function() {
|
||||
var old_value;
|
||||
if (this.next_cl.type === "Delimiter" && this.prev_cl.type !== "Delimiter") {
|
||||
if (!this.is_deleted) {
|
||||
old_value = this.prev_cl.content;
|
||||
this.parent.callEventDecorator([
|
||||
{
|
||||
type: "update",
|
||||
changedBy: this.uid.creator,
|
||||
oldValue: old_value
|
||||
}
|
||||
]);
|
||||
}
|
||||
this.prev_cl.applyDelete();
|
||||
} else if (this.next_cl.type !== "Delimiter") {
|
||||
this.applyDelete();
|
||||
} else {
|
||||
this.parent.callEventDecorator([
|
||||
{
|
||||
type: "add",
|
||||
changedBy: this.uid.creator
|
||||
}
|
||||
]);
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
Replaceable.prototype.callOperationSpecificDeleteEvents = function(o) {
|
||||
if (this.next_cl.type === "Delimiter") {
|
||||
return this.parent.callEventDecorator([
|
||||
{
|
||||
type: "delete",
|
||||
changedBy: o.uid.creator,
|
||||
oldValue: this.content
|
||||
}
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
Replaceable.prototype._encode = function() {
|
||||
var json;
|
||||
json = {
|
||||
'type': this.type,
|
||||
'parent': this.parent.getUid(),
|
||||
'prev': this.prev_cl.getUid(),
|
||||
'next': this.next_cl.getUid(),
|
||||
'uid': this.getUid(),
|
||||
'is_deleted': this.is_deleted
|
||||
};
|
||||
if (this.origin.type === "Delimiter") {
|
||||
json.origin = "Delimiter";
|
||||
} else if (this.origin !== this.prev_cl) {
|
||||
json.origin = this.origin.getUid();
|
||||
}
|
||||
if (this.content instanceof ops.Operation) {
|
||||
json['content'] = this.content.getUid();
|
||||
} else {
|
||||
if ((this.content != null) && (this.content.creator != null)) {
|
||||
throw new Error("You must not set creator here!");
|
||||
}
|
||||
json['content'] = this.content;
|
||||
}
|
||||
return json;
|
||||
};
|
||||
|
||||
return Replaceable;
|
||||
|
||||
})(ops.Insert);
|
||||
ops.Replaceable.parse = function(json) {
|
||||
var content, is_deleted, next, origin, parent, prev, uid;
|
||||
content = json['content'], parent = json['parent'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], is_deleted = json['is_deleted'];
|
||||
return new this(content, parent, uid, prev, next, origin, is_deleted);
|
||||
};
|
||||
return basic_ops;
|
||||
};
|
||||
321
build/node/Operations/Text.js
Normal file
321
build/node/Operations/Text.js
Normal file
@@ -0,0 +1,321 @@
|
||||
var structured_ops_uninitialized,
|
||||
__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; },
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
|
||||
structured_ops_uninitialized = require("./Structured");
|
||||
|
||||
module.exports = function() {
|
||||
var ops, structured_ops;
|
||||
structured_ops = structured_ops_uninitialized();
|
||||
ops = structured_ops.operations;
|
||||
ops.String = (function(_super) {
|
||||
__extends(String, _super);
|
||||
|
||||
function String(uid) {
|
||||
this.textfields = [];
|
||||
String.__super__.constructor.call(this, uid);
|
||||
}
|
||||
|
||||
String.prototype.type = "String";
|
||||
|
||||
String.prototype.val = function() {
|
||||
return this.fold("", function(left, o) {
|
||||
return left + o.val();
|
||||
});
|
||||
};
|
||||
|
||||
String.prototype.toString = function() {
|
||||
return this.val();
|
||||
};
|
||||
|
||||
String.prototype.insert = function(position, content, options) {
|
||||
var ith;
|
||||
ith = this.getOperationByPosition(position);
|
||||
return this.insertAfter(ith, content, options);
|
||||
};
|
||||
|
||||
String.prototype.bind = function(textfield, dom_root) {
|
||||
var createRange, creator_token, t, word, writeContent, writeRange, _i, _len, _ref;
|
||||
if (dom_root == null) {
|
||||
dom_root = window;
|
||||
}
|
||||
if (dom_root.getSelection == null) {
|
||||
dom_root = window;
|
||||
}
|
||||
_ref = this.textfields;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
t = _ref[_i];
|
||||
if (t === textfield) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
creator_token = false;
|
||||
word = this;
|
||||
textfield.value = this.val();
|
||||
this.textfields.push(textfield);
|
||||
if ((textfield.selectionStart != null) && (textfield.setSelectionRange != null)) {
|
||||
createRange = function(fix) {
|
||||
var left, right;
|
||||
left = textfield.selectionStart;
|
||||
right = textfield.selectionEnd;
|
||||
if (fix != null) {
|
||||
left = fix(left);
|
||||
right = fix(right);
|
||||
}
|
||||
return {
|
||||
left: left,
|
||||
right: right
|
||||
};
|
||||
};
|
||||
writeRange = function(range) {
|
||||
writeContent(word.val());
|
||||
return textfield.setSelectionRange(range.left, range.right);
|
||||
};
|
||||
writeContent = function(content) {
|
||||
return textfield.value = content;
|
||||
};
|
||||
} else {
|
||||
createRange = function(fix) {
|
||||
var clength, edited_element, range, s;
|
||||
range = {};
|
||||
s = dom_root.getSelection();
|
||||
clength = textfield.textContent.length;
|
||||
range.left = Math.min(s.anchorOffset, clength);
|
||||
range.right = Math.min(s.focusOffset, clength);
|
||||
if (fix != null) {
|
||||
range.left = fix(range.left);
|
||||
range.right = fix(range.right);
|
||||
}
|
||||
edited_element = s.focusNode;
|
||||
if (edited_element === textfield || edited_element === textfield.childNodes[0]) {
|
||||
range.isReal = true;
|
||||
} else {
|
||||
range.isReal = false;
|
||||
}
|
||||
return range;
|
||||
};
|
||||
writeRange = function(range) {
|
||||
var r, s, textnode;
|
||||
writeContent(word.val());
|
||||
textnode = textfield.childNodes[0];
|
||||
if (range.isReal && (textnode != null)) {
|
||||
if (range.left < 0) {
|
||||
range.left = 0;
|
||||
}
|
||||
range.right = Math.max(range.left, range.right);
|
||||
if (range.right > textnode.length) {
|
||||
range.right = textnode.length;
|
||||
}
|
||||
range.left = Math.min(range.left, range.right);
|
||||
r = document.createRange();
|
||||
r.setStart(textnode, range.left);
|
||||
r.setEnd(textnode, range.right);
|
||||
s = window.getSelection();
|
||||
s.removeAllRanges();
|
||||
return s.addRange(r);
|
||||
}
|
||||
};
|
||||
writeContent = function(content) {
|
||||
var c, content_array, i, _j, _len1, _results;
|
||||
content_array = content.replace(new RegExp("\n", 'g'), " ").split(" ");
|
||||
textfield.innerText = "";
|
||||
_results = [];
|
||||
for (i = _j = 0, _len1 = content_array.length; _j < _len1; i = ++_j) {
|
||||
c = content_array[i];
|
||||
textfield.innerText += c;
|
||||
if (i !== content_array.length - 1) {
|
||||
_results.push(textfield.innerHTML += ' ');
|
||||
} else {
|
||||
_results.push(void 0);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
}
|
||||
writeContent(this.val());
|
||||
this.observe(function(events) {
|
||||
var event, fix, o_pos, r, _j, _len1, _results;
|
||||
_results = [];
|
||||
for (_j = 0, _len1 = events.length; _j < _len1; _j++) {
|
||||
event = events[_j];
|
||||
if (!creator_token) {
|
||||
if (event.type === "insert") {
|
||||
o_pos = event.position;
|
||||
fix = function(cursor) {
|
||||
if (cursor <= o_pos) {
|
||||
return cursor;
|
||||
} else {
|
||||
cursor += 1;
|
||||
return cursor;
|
||||
}
|
||||
};
|
||||
r = createRange(fix);
|
||||
_results.push(writeRange(r));
|
||||
} else if (event.type === "delete") {
|
||||
o_pos = event.position;
|
||||
fix = function(cursor) {
|
||||
if (cursor < o_pos) {
|
||||
return cursor;
|
||||
} else {
|
||||
cursor -= 1;
|
||||
return cursor;
|
||||
}
|
||||
};
|
||||
r = createRange(fix);
|
||||
_results.push(writeRange(r));
|
||||
} else {
|
||||
_results.push(void 0);
|
||||
}
|
||||
} else {
|
||||
_results.push(void 0);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
textfield.onkeypress = function(event) {
|
||||
var char, diff, pos, r;
|
||||
if (word.is_deleted) {
|
||||
textfield.onkeypress = null;
|
||||
return true;
|
||||
}
|
||||
creator_token = true;
|
||||
char = null;
|
||||
if (event.keyCode === 13) {
|
||||
char = '\n';
|
||||
} else if (event.key != null) {
|
||||
if (event.charCode === 32) {
|
||||
char = " ";
|
||||
} else {
|
||||
char = event.key;
|
||||
}
|
||||
} else {
|
||||
char = window.String.fromCharCode(event.keyCode);
|
||||
}
|
||||
if (char.length > 1) {
|
||||
return true;
|
||||
} else if (char.length > 0) {
|
||||
r = createRange();
|
||||
pos = Math.min(r.left, r.right);
|
||||
diff = Math.abs(r.right - r.left);
|
||||
word["delete"](pos, diff);
|
||||
word.insert(pos, char);
|
||||
r.left = pos + char.length;
|
||||
r.right = r.left;
|
||||
writeRange(r);
|
||||
}
|
||||
event.preventDefault();
|
||||
creator_token = false;
|
||||
return false;
|
||||
};
|
||||
textfield.onpaste = function(event) {
|
||||
if (word.is_deleted) {
|
||||
textfield.onpaste = null;
|
||||
return true;
|
||||
}
|
||||
return event.preventDefault();
|
||||
};
|
||||
textfield.oncut = function(event) {
|
||||
if (word.is_deleted) {
|
||||
textfield.oncut = null;
|
||||
return true;
|
||||
}
|
||||
return event.preventDefault();
|
||||
};
|
||||
return textfield.onkeydown = function(event) {
|
||||
var del_length, diff, new_pos, pos, r, val;
|
||||
creator_token = true;
|
||||
if (word.is_deleted) {
|
||||
textfield.onkeydown = null;
|
||||
return true;
|
||||
}
|
||||
r = createRange();
|
||||
pos = Math.min(r.left, r.right, word.val().length);
|
||||
diff = Math.abs(r.left - r.right);
|
||||
if ((event.keyCode != null) && event.keyCode === 8) {
|
||||
if (diff > 0) {
|
||||
word["delete"](pos, diff);
|
||||
r.left = pos;
|
||||
r.right = pos;
|
||||
writeRange(r);
|
||||
} else {
|
||||
if ((event.ctrlKey != null) && event.ctrlKey) {
|
||||
val = word.val();
|
||||
new_pos = pos;
|
||||
del_length = 0;
|
||||
if (pos > 0) {
|
||||
new_pos--;
|
||||
del_length++;
|
||||
}
|
||||
while (new_pos > 0 && val[new_pos] !== " " && val[new_pos] !== '\n') {
|
||||
new_pos--;
|
||||
del_length++;
|
||||
}
|
||||
word["delete"](new_pos, pos - new_pos);
|
||||
r.left = new_pos;
|
||||
r.right = new_pos;
|
||||
writeRange(r);
|
||||
} else {
|
||||
if (pos > 0) {
|
||||
word["delete"](pos - 1, 1);
|
||||
r.left = pos - 1;
|
||||
r.right = pos - 1;
|
||||
writeRange(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
event.preventDefault();
|
||||
creator_token = false;
|
||||
return false;
|
||||
} else if ((event.keyCode != null) && event.keyCode === 46) {
|
||||
if (diff > 0) {
|
||||
word["delete"](pos, diff);
|
||||
r.left = pos;
|
||||
r.right = pos;
|
||||
writeRange(r);
|
||||
} else {
|
||||
word["delete"](pos, 1);
|
||||
r.left = pos;
|
||||
r.right = pos;
|
||||
writeRange(r);
|
||||
}
|
||||
event.preventDefault();
|
||||
creator_token = false;
|
||||
return false;
|
||||
} else {
|
||||
creator_token = false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
String.prototype._encode = function() {
|
||||
var json;
|
||||
json = {
|
||||
'type': this.type,
|
||||
'uid': this.getUid()
|
||||
};
|
||||
return json;
|
||||
};
|
||||
|
||||
return String;
|
||||
|
||||
})(ops.ListManager);
|
||||
ops.String.parse = function(json) {
|
||||
var uid;
|
||||
uid = json['uid'];
|
||||
return new this(uid);
|
||||
};
|
||||
ops.String.create = function(content, mutable) {
|
||||
var word;
|
||||
if (mutable === "mutable") {
|
||||
word = new ops.String().execute();
|
||||
word.insert(0, content);
|
||||
return word;
|
||||
} else if ((mutable == null) || (mutable === "immutable")) {
|
||||
return content;
|
||||
} else {
|
||||
throw new Error("Specify either \"mutable\" or \"immutable\"!!");
|
||||
}
|
||||
};
|
||||
return structured_ops;
|
||||
};
|
||||
Reference in New Issue
Block a user