added text as a custom type, more tests are working

This commit is contained in:
DadaMonad
2015-02-23 11:41:04 +00:00
parent 860934de06
commit 2e9f8f6d03
22 changed files with 2604 additions and 2255 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

@@ -7,7 +7,10 @@ module.exports = function() {
ops = {};
execution_listener = [];
ops.Operation = (function() {
function Operation(uid) {
function Operation(custom_type, uid) {
if (custom_type != null) {
this.custom_type = custom_type;
}
this.is_deleted = false;
this.garbage_collected = false;
this.event_listeners = [];
@@ -181,9 +184,9 @@ module.exports = function() {
ops.Delete = (function(_super) {
__extends(Delete, _super);
function Delete(uid, deletes) {
function Delete(custom_type, uid, deletes) {
this.saveOperation('deletes', deletes);
Delete.__super__.constructor.call(this, uid);
Delete.__super__.constructor.call(this, custom_type, uid);
}
Delete.prototype.type = "Delete";
@@ -215,12 +218,12 @@ module.exports = function() {
ops.Delete.parse = function(o) {
var deletes_uid, uid;
uid = o['uid'], deletes_uid = o['deletes'];
return new this(uid, deletes_uid);
return new this(null, uid, deletes_uid);
};
ops.Insert = (function(_super) {
__extends(Insert, _super);
function Insert(content, uid, prev_cl, next_cl, origin, parent) {
function Insert(custom_type, content, uid, prev_cl, next_cl, origin, parent) {
if (content === void 0) {
} else if ((content != null) && (content.creator != null)) {
@@ -236,7 +239,7 @@ module.exports = function() {
} else {
this.saveOperation('origin', prev_cl);
}
Insert.__super__.constructor.call(this, uid);
Insert.__super__.constructor.call(this, custom_type, uid);
}
Insert.prototype.type = "Insert";
@@ -371,14 +374,21 @@ module.exports = function() {
};
Insert.prototype.callOperationSpecificInsertEvents = function() {
var _ref;
var getContentType, _ref;
getContentType = function(content) {
if (content instanceof ops.Operation) {
return content.getCustomType();
} else {
return content;
}
};
return (_ref = this.parent) != null ? _ref.callEvent([
{
type: "insert",
position: this.getPosition(),
object: this.parent,
object: this.parent.getCustomType(),
changedBy: this.uid.creator,
value: this.content
value: getContentType(this.content)
}
]) : void 0;
};
@@ -388,7 +398,7 @@ module.exports = function() {
{
type: "delete",
position: this.getPosition(),
object: this.parent,
object: this.parent.getCustomType(),
length: 1,
changedBy: o.uid.creator
}
@@ -442,14 +452,14 @@ module.exports = function() {
if (typeof content === "string") {
content = JSON.parse(content);
}
return new this(content, uid, prev, next, origin, parent);
return new this(null, content, uid, prev, next, origin, parent);
};
ops.ImmutableObject = (function(_super) {
__extends(ImmutableObject, _super);
function ImmutableObject(uid, _at_content) {
function ImmutableObject(custom_type, uid, _at_content) {
this.content = _at_content;
ImmutableObject.__super__.constructor.call(this, uid);
ImmutableObject.__super__.constructor.call(this, custom_type, uid);
}
ImmutableObject.prototype.type = "ImmutableObject";
@@ -474,7 +484,7 @@ module.exports = function() {
ops.ImmutableObject.parse = function(json) {
var content, uid;
uid = json['uid'], content = json['content'];
return new this(uid, content);
return new this(null, uid, content);
};
ops.Delimiter = (function(_super) {
__extends(Delimiter, _super);
@@ -483,7 +493,7 @@ module.exports = function() {
this.saveOperation('prev_cl', prev_cl);
this.saveOperation('next_cl', next_cl);
this.saveOperation('origin', prev_cl);
Delimiter.__super__.constructor.call(this, {
Delimiter.__super__.constructor.call(this, null, {
noOperation: true
});
}

View File

@@ -12,11 +12,8 @@ module.exports = function() {
__extends(MapManager, _super);
function MapManager(custom_type, uid) {
if (custom_type != null) {
this.custom_type = custom_type;
}
this._map = {};
MapManager.__super__.constructor.call(this, uid);
MapManager.__super__.constructor.call(this, custom_type, uid);
}
MapManager.prototype.type = "MapManager";
@@ -48,8 +45,8 @@ module.exports = function() {
MapManager.prototype.val = function(name, content) {
var o, prop, rep, res, result, _ref;
if (arguments.length > 1) {
if ((content != null) && (content._model != null) && content._model instanceof ops.Operation) {
rep = content._model;
if ((content != null) && (content._getModel != null)) {
rep = content._getModel(this.custom_types, this.operations);
} else {
rep = content;
}
@@ -73,12 +70,7 @@ module.exports = function() {
for (name in _ref) {
o = _ref[name];
if (!o.isContentDeleted()) {
res = prop.val();
if (res instanceof ops.Operation) {
result[name] = res.getCustomType();
} else {
result[name] = res;
}
result[name] = o.val();
}
}
return result;
@@ -105,7 +97,7 @@ module.exports = function() {
sub: property_name,
alt: this
};
rm = new ops.ReplaceManager(event_properties, event_this, rm_uid);
rm = new ops.ReplaceManager(null, event_properties, event_this, rm_uid);
this._map[property_name] = rm;
rm.setParent(this, property_name);
rm.execute();
@@ -138,13 +130,13 @@ module.exports = function() {
ops.ListManager = (function(_super) {
__extends(ListManager, _super);
function ListManager(uid) {
function ListManager(custom_type, 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.__super__.constructor.call(this, custom_type, uid);
}
ListManager.prototype.type = "ListManager";
@@ -281,42 +273,29 @@ module.exports = function() {
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;
}
};
ListManager.prototype.insertAfter = function(left, content) {
var c, right, tmp, _i, _len;
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();
(new ops.Insert(null, 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();
tmp = (new ops.Insert(null, c, void 0, left, right)).execute();
left = tmp;
}
}
return this;
};
ListManager.prototype.insert = function(position, content, options) {
ListManager.prototype.insert = function(position, content) {
var ith;
ith = this.getOperationByPosition(position);
return this.insertAfter(ith, [content], options);
return this.insertAfter(ith, [content]);
};
ListManager.prototype["delete"] = function(position, length) {
@@ -327,7 +306,7 @@ module.exports = function() {
if (o instanceof ops.Delimiter) {
break;
}
d = (new ops.Delete(void 0, o)).execute();
d = (new ops.Delete(null, void 0, o)).execute();
o = o.next_cl;
while ((!(o instanceof ops.Delimiter)) && o.isDeleted()) {
o = o.next_cl;
@@ -343,6 +322,11 @@ module.exports = function() {
'type': this.type,
'uid': this.getUid()
};
if (this.custom_type.constructor === String) {
json.custom_type = this.custom_type;
} else {
json.custom_type = this.custom_type._name;
}
return json;
};
@@ -350,34 +334,20 @@ module.exports = function() {
})(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\"!!");
}
var custom_type, uid;
uid = json['uid'], custom_type = json['custom_type'];
return new this(custom_type, uid);
};
ops.ReplaceManager = (function(_super) {
__extends(ReplaceManager, _super);
function ReplaceManager(_at_event_properties, _at_event_this, uid, beginning, end) {
function ReplaceManager(custom_type, _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.__super__.constructor.call(this, custom_type, uid, beginning, end);
}
ReplaceManager.prototype.type = "ReplaceManager";
@@ -415,7 +385,7 @@ module.exports = function() {
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();
relp = (new ops.Replaceable(null, content, this, replaceable_uid, o, o.next_cl)).execute();
return void 0;
};
@@ -424,7 +394,7 @@ module.exports = function() {
};
ReplaceManager.prototype.deleteContent = function() {
(new ops.Delete(void 0, this.getLastOperation().uid)).execute();
(new ops.Delete(null, void 0, this.getLastOperation().uid)).execute();
return void 0;
};
@@ -451,9 +421,9 @@ module.exports = function() {
ops.Replaceable = (function(_super) {
__extends(Replaceable, _super);
function Replaceable(content, parent, uid, prev, next, origin, is_deleted) {
function Replaceable(custom_type, content, parent, uid, prev, next, origin, is_deleted) {
this.saveOperation('parent', parent);
Replaceable.__super__.constructor.call(this, content, uid, prev, next, origin);
Replaceable.__super__.constructor.call(this, custom_type, content, uid, prev, next, origin);
this.is_deleted = is_deleted;
}
@@ -560,9 +530,9 @@ module.exports = function() {
})(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);
var content, custom_type, 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'], custom_type = json['custom_type'];
return new this(custom_type, content, parent, uid, prev, next, origin, is_deleted);
};
return basic_ops;
};

View File

@@ -63,6 +63,10 @@ YObject = (function() {
}
};
YObject.prototype["delete"] = function(name) {
return this._model["delete"](name);
};
return YObject;
})();

335
build/node/Types/Text.js Normal file
View File

@@ -0,0 +1,335 @@
var YText;
YText = (function() {
function YText(text) {
this.textfields = [];
if (text == null) {
this._text = "";
} else if (text.constructor === String) {
this._text = text;
} else {
throw new Error("Y.Text expects a String as a constructor");
}
}
YText.prototype._name = "Text";
YText.prototype._getModel = function(types, ops) {
if (this._model == null) {
this._model = new ops.ListManager(this).execute();
this.insert(0, this._text);
}
delete this._text;
return this._model;
};
YText.prototype._setModel = function(_at__model) {
this._model = _at__model;
return delete this._text;
};
YText.prototype.val = function() {
return this._model.fold("", function(left, o) {
return left + o.val();
});
};
YText.prototype.observe = function() {
return this._model.observe.apply(this._model, arguments);
};
YText.prototype.unobserve = function() {
return this._model.unobserve.apply(this._model, arguments);
};
YText.prototype.toString = function() {
return this.val();
};
YText.prototype.insert = function(position, content) {
var ith;
if (content.constructor !== String) {
throw new Error("Y.String.insert expects a String as the second parameter!");
}
if (typeof position !== "number") {
throw new Error("Y.String.insert expects a Number as the second parameter!");
}
if (content.length > 0) {
ith = this._model.getOperationByPosition(position);
return this._model.insertAfter(ith, content);
}
};
YText.prototype["delete"] = function(position, length) {
return this._model["delete"](position, length);
};
YText.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 += '&nbsp;');
} 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;
}
};
};
return YText;
})();
if (typeof window !== "undefined" && window !== null) {
if (window.Y != null) {
window.Y.Text = YText;
} else {
throw new Error("You must first import Y!");
}
}
if (typeof module !== "undefined" && module !== null) {
module.exports = YText;
}

View File

@@ -1,6 +1,6 @@
var Engine, HistoryBuffer, adaptConnector, createY, text_ops_uninitialized;
var Engine, HistoryBuffer, adaptConnector, createY, structured_ops_uninitialized;
text_ops_uninitialized = require("./Operations/Text");
structured_ops_uninitialized = require("./Operations/Structured");
HistoryBuffer = require("./HistoryBuffer");
@@ -21,7 +21,7 @@ createY = function(connector) {
};
}
HB = new HistoryBuffer(user_id);
ops_manager = text_ops_uninitialized(HB, this.constructor);
ops_manager = structured_ops_uninitialized(HB, this.constructor);
ops = ops_manager.operations;
engine = new Engine(HB, ops);
adaptConnector(connector, engine, HB, ops_manager.execution_listener);
@@ -29,7 +29,7 @@ createY = function(connector) {
ops.Operation.prototype.operations = ops;
ops.Operation.prototype.engine = engine;
ops.Operation.prototype.connector = connector;
ops.Operation.prototype.custom_ops = this.constructor;
ops.Operation.prototype.custom_types = this.constructor;
ct = new createY.Object();
model = new ops.MapManager(ct, HB.getReservedUniqueIdentifier()).execute();
ct._setModel(model);
@@ -43,3 +43,5 @@ if (typeof window !== "undefined" && window !== null) {
}
createY.Object = require("./Types/Object");
createY.Text = require("./Types/Text");

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long