completed the xml tests - and lots of them run successfully

This commit is contained in:
DadaMonad
2015-02-26 18:28:35 +00:00
parent f9542b90db
commit f932f560bd
15 changed files with 10528 additions and 740 deletions
File diff suppressed because one or more lines are too long
+3 -2
View File
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -433,7 +433,8 @@ module.exports = function() {
position: this.getPosition(), position: this.getPosition(),
object: this.parent.getCustomType(), object: this.parent.getCustomType(),
length: 1, length: 1,
changedBy: o.uid.creator changedBy: o.uid.creator,
oldValue: this.val()
} }
]); ]);
}; };
+4 -311
View File
@@ -1,50 +1,11 @@
var dont_proxy, json_types_uninitialized, proxy_token, _proxy, var json_types_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; }, __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; __hasProp = {}.hasOwnProperty;
json_types_uninitialized = require("./JsonTypes"); json_types_uninitialized = require("./JsonTypes");
proxy_token = false;
dont_proxy = function(f) {
var e;
proxy_token = true;
try {
f();
} catch (_error) {
e = _error;
proxy_token = false;
throw new Error(e);
}
return proxy_token = false;
};
_proxy = function(f_name, f) {
var old_f;
old_f = this[f_name];
if (old_f != null) {
return this[f_name] = function() {
var args, that, _ref;
if (!proxy_token && !((_ref = this._y) != null ? _ref.isDeleted() : void 0)) {
that = this;
args = arguments;
return dont_proxy(function() {
f.apply(that, args);
return old_f.apply(that, args);
});
} else {
return old_f.apply(this, arguments);
}
};
}
};
if (typeof Element !== "undefined" && Element !== null) {
Element.prototype._proxy = _proxy;
}
module.exports = function(HB) { module.exports = function(HB) {
var TextNodeType, XmlType, json_types, parser, types; var XmlType, json_types, parser, types;
json_types = json_types_uninitialized(HB); json_types = json_types_uninitialized(HB);
types = json_types.types; types = json_types.types;
parser = json_types.parser; parser = json_types.parser;
@@ -52,234 +13,11 @@ module.exports = function(HB) {
__extends(XmlType, _super); __extends(XmlType, _super);
function XmlType(uid, _at_tagname, attributes, elements, _at_xml) { function XmlType(uid, _at_tagname, attributes, elements, _at_xml) {
var attr, d, element, i, n, word, _i, _j, _len, _ref, _ref1, _ref2;
this.tagname = _at_tagname; this.tagname = _at_tagname;
this.xml = _at_xml; this.xml = _at_xml;
/* In case you make this instanceof Insert again
if prev? and (not next?) and prev.type?
* adjust what you actually mean. you want to insert after prev, then
* next is not defined. but we only insert after non-deleted elements.
* This is also handled in TextInsert.
while prev.isDeleted()
prev = prev.prev_cl
next = prev.next_cl
*/
XmlType.__super__.constructor.call(this, uid);
if (((_ref = this.xml) != null ? _ref._y : void 0) != null) {
d = new types.Delete(void 0, this.xml._y);
HB.addOperation(d).execute();
this.xml._y = null;
}
if ((attributes != null) && (elements != null)) {
this.saveOperation('attributes', attributes);
this.saveOperation('elements', elements);
} else if ((attributes == null) && (elements == null)) {
this.attributes = new types.JsonType();
this.attributes.setMutableDefault('immutable');
HB.addOperation(this.attributes).execute();
this.elements = new types.WordType();
this.elements.parent = this;
HB.addOperation(this.elements).execute();
} else {
throw new Error("Either define attribute and elements both, or none of them");
}
if (this.xml != null) {
this.tagname = this.xml.tagName;
for (i = _i = 0, _ref1 = this.xml.attributes.length; 0 <= _ref1 ? _i < _ref1 : _i > _ref1; i = 0 <= _ref1 ? ++_i : --_i) {
attr = xml.attributes[i];
this.attributes.val(attr.name, attr.value);
}
_ref2 = this.xml.childNodes;
for (_j = 0, _len = _ref2.length; _j < _len; _j++) {
n = _ref2[_j];
if (n.nodeType === n.TEXT_NODE) {
word = new TextNodeType(void 0, n);
HB.addOperation(word).execute();
this.elements.push(word);
} else if (n.nodeType === n.ELEMENT_NODE) {
element = new XmlType(void 0, void 0, void 0, void 0, n);
HB.addOperation(element).execute();
this.elements.push(element);
} else {
throw new Error("I don't know Node-type " + n.nodeType + "!!");
}
}
this.setXmlProxy();
}
void 0;
} }
XmlType.prototype.type = "XmlType"; XmlType.prototype.setXmlProxy = function() {};
XmlType.prototype.applyDelete = function(op) {
if ((this.insert_parent != null) && !this.insert_parent.isDeleted()) {
return this.insert_parent.applyDelete(op);
} else {
this.attributes.applyDelete();
this.elements.applyDelete();
return XmlType.__super__.applyDelete.apply(this, arguments);
}
};
XmlType.prototype.cleanup = function() {
return XmlType.__super__.cleanup.call(this);
};
XmlType.prototype.setXmlProxy = function() {
var findNode, insertBefore, removeChild, renewClassList, that;
this.xml._y = this;
that = this;
this.elements.on('insert', function(event, op) {
var newNode, right, rightNode;
if (op.creator !== HB.getUserId() && this === that.elements) {
newNode = op.content.val();
right = op.next_cl;
while ((right != null) && right.isDeleted()) {
right = right.next_cl;
}
rightNode = null;
if (right.type !== 'Delimiter') {
rightNode = right.val().val();
}
return dont_proxy(function() {
return that.xml.insertBefore(newNode, rightNode);
});
}
});
this.elements.on('delete', function(event, op) {
var del_op, deleted;
del_op = op.deleted_by[0];
if ((del_op != null) && del_op.creator !== HB.getUserId() && this === that.elements) {
deleted = op.content.val();
return dont_proxy(function() {
return that.xml.removeChild(deleted);
});
}
});
this.attributes.on(['add', 'update'], function(event, property_name, op) {
if (op.creator !== HB.getUserId() && this === that.attributes) {
return dont_proxy(function() {
var newval;
newval = op.val().val();
if (newval != null) {
return that.xml.setAttribute(property_name, op.val().val());
} else {
return that.xml.removeAttribute(property_name);
}
});
}
});
findNode = function(child) {
var elem;
if (child == null) {
throw new Error("you must specify a parameter!");
}
child = child._y;
elem = that.elements.beginning.next_cl;
while (elem.type !== 'Delimiter' && elem.content !== child) {
elem = elem.next_cl;
}
if (elem.type === 'Delimiter') {
return false;
} else {
return elem;
}
};
insertBefore = function(insertedNode_s, adjacentNode) {
var child, element, inserted_nodes, next, prev, _results;
next = null;
if (adjacentNode != null) {
next = findNode(adjacentNode);
}
prev = null;
if (next) {
prev = next.prev_cl;
} else {
prev = this._y.elements.end.prev_cl;
while (prev.isDeleted()) {
prev = prev.prev_cl;
}
}
inserted_nodes = null;
if (insertedNode_s.nodeType === insertedNode_s.DOCUMENT_FRAGMENT_NODE) {
child = insertedNode_s.lastChild;
_results = [];
while (child != null) {
element = new XmlType(void 0, void 0, void 0, void 0, child);
HB.addOperation(element).execute();
that.elements.insertAfter(prev, element);
_results.push(child = child.previousSibling);
}
return _results;
} else {
element = new XmlType(void 0, void 0, void 0, void 0, insertedNode_s);
HB.addOperation(element).execute();
return that.elements.insertAfter(prev, element);
}
};
this.xml._proxy('insertBefore', insertBefore);
this.xml._proxy('appendChild', insertBefore);
this.xml._proxy('removeAttribute', function(name) {
return that.attributes.val(name, void 0);
});
this.xml._proxy('setAttribute', function(name, value) {
return that.attributes.val(name, value);
});
renewClassList = function(newclass) {
var dont_do_it, elem, value, _i, _len;
dont_do_it = false;
if (newclass != null) {
for (_i = 0, _len = this.length; _i < _len; _i++) {
elem = this[_i];
if (newclass === elem) {
dont_do_it = true;
}
}
}
value = Array.prototype.join.call(this, " ");
if ((newclass != null) && !dont_do_it) {
value += " " + newclass;
}
return that.attributes.val('class', value);
};
_proxy.call(this.xml.classList, 'add', renewClassList);
_proxy.call(this.xml.classList, 'remove', renewClassList);
this.xml.__defineSetter__('className', function(val) {
return this.setAttribute('class', val);
});
this.xml.__defineGetter__('className', function() {
return that.attributes.val('class');
});
this.xml.__defineSetter__('textContent', function(val) {
var elem, remove, text_node;
elem = that.xml.firstChild;
while (elem != null) {
remove = elem;
elem = elem.nextSibling;
that.xml.removeChild(remove);
}
if (val !== "") {
text_node = document.createTextNode(val);
return that.xml.appendChild(text_node);
}
});
removeChild = function(node) {
var d, elem;
elem = findNode(node);
if (!elem) {
throw new Error("You are only allowed to delete existing (direct) child elements!");
}
d = new types.Delete(void 0, elem);
HB.addOperation(d).execute();
return node._y = null;
};
this.xml._proxy('removeChild', removeChild);
return this.xml._proxy('replaceChild', function(insertedNode, replacedNode) {
insertBefore.call(this, insertedNode, replacedNode);
return removeChild.call(this, replacedNode);
});
};
XmlType.prototype.val = function(enforce) { XmlType.prototype.val = function(enforce) {
var a, attr, attr_name, e, n, text_node, value; var a, attr, attr_name, e, n, text_node, value;
@@ -351,54 +89,9 @@ module.exports = function(HB) {
return XmlType; return XmlType;
})(types.Insert); })(types.Insert);
parser['XmlType'] = function(json) { return parser['XmlType'] = function(json) {
var attributes, elements, tagname, uid; var attributes, elements, tagname, uid;
uid = json['uid'], attributes = json['attributes'], elements = json['elements'], tagname = json['tagname']; uid = json['uid'], attributes = json['attributes'], elements = json['elements'], tagname = json['tagname'];
return new XmlType(uid, tagname, attributes, elements, void 0); return new XmlType(uid, tagname, attributes, elements, void 0);
}; };
TextNodeType = (function(_super) {
__extends(TextNodeType, _super);
function TextNodeType(uid, content) {
var d;
if (content._y != null) {
d = new types.Delete(void 0, content._y);
HB.addOperation(d).execute();
content._y = null;
}
content._y = this;
TextNodeType.__super__.constructor.call(this, uid, content);
}
TextNodeType.prototype.applyDelete = function(op) {
if ((this.insert_parent != null) && !this.insert_parent.isDeleted()) {
return this.insert_parent.applyDelete(op);
} else {
return TextNodeType.__super__.applyDelete.apply(this, arguments);
}
};
TextNodeType.prototype.type = "TextNodeType";
TextNodeType.prototype._encode = function() {
var json;
json = {
'type': this.type,
'uid': this.getUid(),
'content': this.content.textContent
};
return json;
};
return TextNodeType;
})(types.ImmutableObject);
parser['TextNodeType'] = function(json) {
var content, textnode, uid;
uid = json['uid'], content = json['content'];
textnode = document.createTextNode(content);
return new TextNodeType(uid, textnode);
};
types['XmlType'] = XmlType;
return json_types;
}; };
+304 -36
View File
@@ -1,78 +1,131 @@
var YXml; var YXml, dont_proxy, initialize_proxies, proxies_are_initialized, proxy_token;
YXml = (function() { YXml = (function() {
function YXml(tagname, attributes) { function YXml(tag_or_dom, attributes) {
var a, a_name, c, c_name, _classes, _i, _len, _ref; var a, a_name, c, c_name, tagname, _classes, _i, _len, _ref;
if (attributes == null) { if (attributes == null) {
attributes = {}; attributes = {};
} }
this._xml = {}; if (tag_or_dom == null) {
this._xml.tagname = tagname;
if (attributes.constructor !== Object) { } else if (tag_or_dom.constructor === String) {
throw new Error("The attributes must be specified as a Object"); tagname = tag_or_dom;
} this._xml = {};
for (a_name in attributes) { this._xml.children = [];
a = attributes[a_name]; this._xml.tagname = tagname;
if (a.constructor !== String) { if (attributes.constructor !== Object) {
throw new Error("The attributes must be of type String!"); throw new Error("The attributes must be specified as a Object");
} }
} for (a_name in attributes) {
this._xml.attributes = attributes; a = attributes[a_name];
this._xml.classes = {}; if (a.constructor !== String) {
_classes = this._xml.attributes["class"]; throw new Error("The attributes must be of type String!");
delete this._xml.attributes["class"];
if (_classes != null) {
_ref = _classes.split(" ");
for (c = _i = 0, _len = _ref.length; _i < _len; c = ++_i) {
c_name = _ref[c];
if (c.length > 0) {
this._xml.classes[c_name] = c;
} }
} }
this._xml.attributes = attributes;
this._xml.classes = {};
_classes = this._xml.attributes["class"];
delete this._xml.attributes["class"];
if (_classes != null) {
_ref = _classes.split(" ");
for (c = _i = 0, _len = _ref.length; _i < _len; c = ++_i) {
c_name = _ref[c];
if (c.length > 0) {
this._xml.classes[c_name] = c;
}
}
}
void 0;
} else if (tag_or_dom instanceof Element) {
this._dom = tag_or_dom;
this._xml = {};
} }
void 0;
} }
YXml.prototype._name = "Xml"; YXml.prototype._name = "Xml";
YXml.prototype._getModel = function(Y, ops) { YXml.prototype._getModel = function(Y, ops) {
var attribute, c, child, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
if (this._model == null) { if (this._model == null) {
if (this._dom != null) {
this._xml.tagname = this._dom.tagName.toLowerCase();
this._xml.attributes = {};
this._xml.classes = {};
_ref = this._dom.attributes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
attribute = _ref[_i];
if (attribute.name === "class") {
_ref1 = attribute.value.split(" ");
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
c = _ref1[_j];
this._xml.classes[c] = true;
}
} else {
this._xml.attributes[attribute.name] = attribute.value;
}
}
this._xml.children = [];
_ref2 = this._dom.childNodes;
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
child = _ref2[_k];
if (child.nodeType === child.TEXT_NODE) {
this._xml.children.push(child.textContent);
} else {
this._xml.children.push(new YXml(child));
}
}
}
this._model = new ops.MapManager(this).execute(); this._model = new ops.MapManager(this).execute();
this._model.val("attributes", new Y.Object(this._xml.attributes)); this._model.val("attributes", new Y.Object(this._xml.attributes));
this._model.val("classes", new Y.Object(this._xml.classes)); this._model.val("classes", new Y.Object(this._xml.classes));
this._model.val("tagname", this._xml.tagname); this._model.val("tagname", this._xml.tagname);
this._model.val("children", new Y.List()); this._model.val("children", new Y.List(this._xml.children));
if (this._xml.parent != null) { if (this._xml.parent != null) {
this._model.val("parent", this._xml.parent); this._model.val("parent", this._xml.parent);
} }
if (this._dom != null) {
this.getDom();
}
this._setModel(this._model);
} }
this._setModel(this._model);
return this._model; return this._model;
}; };
YXml.prototype._setModel = function(_at__model) { YXml.prototype._setModel = function(_at__model) {
this._model = _at__model; this._model = _at__model;
delete this._xml; this._model.observe(function(events) {
return this._model.observe(function(events) { var c, children, event, i, parent, _i, _len, _ref, _results;
var c, children, event, i, parent, _i, _j, _len, _len1, _ref; _results = [];
for (_i = 0, _len = events.length; _i < _len; _i++) { for (_i = 0, _len = events.length; _i < _len; _i++) {
event = events[_i]; event = events[_i];
if (event.name === "parent" && event.type !== "add") { if (event.name === "parent" && event.type !== "add") {
parent = event.oldValue; parent = event.oldValue;
children = (_ref = parent._model.val("children")) != null ? _ref.val() : void 0; children = (_ref = parent._model.val("children")) != null ? _ref.val() : void 0;
if (children != null) { if (children != null) {
for (i = _j = 0, _len1 = children.length; _j < _len1; i = ++_j) { _results.push((function() {
c = children[i]; var _j, _len1, _results1;
if (c === this) { _results1 = [];
parent._model.val("children")["delete"](i); for (i = _j = 0, _len1 = children.length; _j < _len1; i = ++_j) {
break; c = children[i];
if (c === this) {
parent._model.val("children")["delete"](i);
break;
} else {
_results1.push(void 0);
}
} }
} return _results1;
}).call(this));
} else {
_results.push(void 0);
} }
} else {
_results.push(void 0);
} }
} }
return void 0; return _results;
}); });
return delete this._xml;
}; };
YXml.prototype._setParent = function(parent) { YXml.prototype._setParent = function(parent) {
@@ -294,10 +347,225 @@ YXml = (function() {
return this._model.val("children").val(); return this._model.val("children").val();
}; };
YXml.prototype.getPosition = function() {
var c, i, parent, _i, _len, _ref;
parent = this._model.val("parent");
if (parent != null) {
_ref = parent._model.val("children").val();
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
c = _ref[i];
if (c === this) {
return i;
}
}
throw new Error("This is not a child of its parent (should not happen in Y.Xml!)");
} else {
return null;
}
};
YXml.prototype.getDom = function() {
var attr_name, attr_value, child, dom, i, that, _i, _len, _ref, _ref1;
if (this._dom == null) {
this._dom = document.createElement(this._model.val("tagname"));
_ref = this.attr();
for (attr_name in _ref) {
attr_value = _ref[attr_name];
this._dom.setAttribute(attr_name, attr_value);
}
_ref1 = this.getChildren();
for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
child = _ref1[i];
if (child.constructor === String) {
dom = document.createTextNode(child);
} else {
dom = child.getDom();
}
this._dom.insertBefore(dom);
}
}
that = this;
if (this._dom._y_xml == null) {
this._dom._y_xml = this;
initialize_proxies.call(this);
this._model.val("children").observe(function(events) {
var children, deleted, event, newNode, rightNode, _j, _len1, _results;
_results = [];
for (_j = 0, _len1 = events.length; _j < _len1; _j++) {
event = events[_j];
if (event.type === "insert") {
newNode = event.value.getDom();
children = that._dom.childNodes;
if (children.length > 0) {
rightNode = children[0];
} else {
rightNode = null;
}
event.value._setParent(that);
_results.push(dont_proxy(function() {
return that._dom.insertBefore(newNode, rightNode);
}));
} else if (event.type === "delete") {
deleted = event.oldValue.getDom();
_results.push(dont_proxy(function() {
return that._dom.removeChild(deleted);
}));
} else {
_results.push(void 0);
}
}
return _results;
});
this._model.val("attributes").observe(function(events) {
var event, newval, _j, _len1, _results;
_results = [];
for (_j = 0, _len1 = events.length; _j < _len1; _j++) {
event = events[_j];
if (event.type === "add" || event.type === "update") {
newval = event.object.val(event.name);
_results.push(dont_proxy(function() {
return that._dom.setAttribute(event.name, newval);
}));
} else if (event.type === "delete") {
_results.push(dont_proxy(function() {
return that._dom.removeAttribute(event.name);
}));
} else {
_results.push(void 0);
}
}
return _results;
});
this._model.val("classes").observe(function(events) {
var event, _j, _len1, _results;
_results = [];
for (_j = 0, _len1 = events.length; _j < _len1; _j++) {
event = events[_j];
if (event.type === "add" || event.type === "update") {
_results.push(dont_proxy(function() {
return that._dom.classList.add(event.name);
}));
} else if (event.type === "delete") {
_results.push(dont_proxy(function() {
return that._dom.classList.remove(event.name);
}));
} else {
_results.push(void 0);
}
}
return _results;
});
}
return this._dom;
};
return YXml; return YXml;
})(); })();
proxies_are_initialized = false;
proxy_token = false;
dont_proxy = function(f) {
var e;
proxy_token = true;
try {
f();
} catch (_error) {
e = _error;
proxy_token = false;
throw new Error(e);
}
return proxy_token = false;
};
initialize_proxies = function() {
var insertBefore, removeChild, replaceChild, that, _proxy;
_proxy = function(f_name, f, source) {
var old_f;
if (source == null) {
source = Element.prototype;
}
old_f = source[f_name];
return source[f_name] = function() {
if ((this._y_xml == null) || proxy_token) {
return old_f.apply(this, arguments);
} else {
return f.apply(this._y_xml, arguments);
}
};
};
that = this;
this._dom.classList.add = function(c) {
return that.addClass(c);
};
this._dom.classList.remove = function(c) {
return that.removeClass(c);
};
this._dom.__defineSetter__('className', function(val) {
return that.attr('class', val);
});
this._dom.__defineGetter__('className', function() {
return that.attr('class');
});
this._dom.__defineSetter__('textContent', function(val) {
that.empty();
if (val !== "") {
return that.append(val);
}
});
if (proxies_are_initialized) {
return;
}
proxies_are_initialized = true;
insertBefore = function(insertedNode_s, adjacentNode) {
var child, new_childs, pos;
if (adjacentNode != null) {
pos = adjacentNode._y_xml.getPosition();
} else {
pos = this.getChildren().length;
}
new_childs = [];
if (insertedNode_s.nodeType === insertedNode_s.DOCUMENT_FRAGMENT_NODE) {
child = insertedNode_s.firstChild;
while (child != null) {
new_childs.push(child);
child = child.nextSibling;
}
} else {
new_childs.push(insertedNode_s);
}
new_childs = new_childs.map(function(child) {
if (child._y_xml != null) {
return child._y_xml;
} else if (child.nodeType === child.TEXT_NODE) {
return child.textContent;
} else {
return new YXml(child);
}
});
return this._model.val("children").insertContents(pos, new_childs);
};
_proxy('insertBefore', insertBefore);
_proxy('appendChild', insertBefore);
_proxy('removeAttribute', function(name) {
return this.removeAttr(name);
});
_proxy('setAttribute', function(name, value) {
return this.attr(name, value);
});
removeChild = function(node) {
return node._y_xml.remove();
};
_proxy('removeChild', removeChild, this._dom);
replaceChild = function(insertedNode, replacedNode) {
insertBefore.call(this, insertedNode, replacedNode);
return removeChild.call(this, replacedNode);
};
return _proxy('replaceChild', replaceChild, this._dom);
};
if (typeof window !== "undefined" && window !== null) { if (typeof window !== "undefined" && window !== null) {
if (window.Y != null) { if (window.Y != null) {
window.Y.Xml = YXml; window.Y.Xml = YXml;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+9774 -78
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -2,7 +2,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Test Yjs!</title> <title>Test Yjs!</title>
<link rel="stylesheet" href="../../node_modules/mocha/mocha.css" /> <link rel="stylesheet" href="../../node_modules/mocha/mocha.css" />
</head> </head>
<body> <body>
<div id="mocha"></div> <div id="mocha"></div>
+1
View File
@@ -487,6 +487,7 @@ module.exports = ()->
object: @parent.getCustomType() # TODO: You can combine getPosition + getParent in a more efficient manner! (only left Delimiter will hold @parent) object: @parent.getCustomType() # TODO: You can combine getPosition + getParent in a more efficient manner! (only left Delimiter will hold @parent)
length: 1 length: 1
changedBy: o.uid.creator changedBy: o.uid.creator
oldValue: @val()
] ]
# #
-269
View File
@@ -1,34 +1,7 @@
json_types_uninitialized = require "./JsonTypes" json_types_uninitialized = require "./JsonTypes"
# some dom implementations may call another dom.method that simulates the behavior of another.
# For example xml.insertChild(dom) , wich inserts an element at the end, and xml.insertAfter(dom,null) wich does the same
# But Y's proxy may be called only once!
proxy_token = false
dont_proxy = (f)->
proxy_token = true
try
f()
catch e
proxy_token = false
throw new Error e
proxy_token = false
_proxy = (f_name, f)->
old_f = @[f_name]
if old_f?
@[f_name] = ()->
if not proxy_token and not @_y?.isDeleted()
that = this
args = arguments
dont_proxy ()->
f.apply that, args
old_f.apply that, args
else
old_f.apply this, arguments
#else
# @[f_name] = f
Element?.prototype._proxy = _proxy
module.exports = (HB)-> module.exports = (HB)->
@@ -46,202 +19,10 @@ module.exports = (HB)->
class XmlType extends types.Insert class XmlType extends types.Insert
constructor: (uid, @tagname, attributes, elements, @xml)-> constructor: (uid, @tagname, attributes, elements, @xml)->
### In case you make this instanceof Insert again
if prev? and (not next?) and prev.type?
# adjust what you actually mean. you want to insert after prev, then
# next is not defined. but we only insert after non-deleted elements.
# This is also handled in TextInsert.
while prev.isDeleted()
prev = prev.prev_cl
next = prev.next_cl
###
super(uid)
if @xml?._y?
d = new types.Delete undefined, @xml._y
HB.addOperation(d).execute()
@xml._y = null
if attributes? and elements?
@saveOperation 'attributes', attributes
@saveOperation 'elements', elements
else if (not attributes?) and (not elements?)
@attributes = new types.JsonType()
@attributes.setMutableDefault 'immutable'
HB.addOperation(@attributes).execute()
@elements = new types.WordType()
@elements.parent = @
HB.addOperation(@elements).execute()
else
throw new Error "Either define attribute and elements both, or none of them"
if @xml?
@tagname = @xml.tagName
for i in [0...@xml.attributes.length]
attr = xml.attributes[i]
@attributes.val(attr.name, attr.value)
for n in @xml.childNodes
if n.nodeType is n.TEXT_NODE
word = new TextNodeType(undefined, n)
HB.addOperation(word).execute()
@elements.push word
else if n.nodeType is n.ELEMENT_NODE
element = new XmlType undefined, undefined, undefined, undefined, n
HB.addOperation(element).execute()
@elements.push element
else
throw new Error "I don't know Node-type #{n.nodeType}!!"
@setXmlProxy()
undefined
#
# Identifies this class.
# Use it in order to check whether this is an xml-type or something else.
#
type: "XmlType"
applyDelete: (op)->
if @insert_parent? and not @insert_parent.isDeleted()
@insert_parent.applyDelete op
else
@attributes.applyDelete()
@elements.applyDelete()
super
cleanup: ()->
super()
setXmlProxy: ()-> setXmlProxy: ()->
@xml._y = @
that = @
@elements.on 'insert', (event, op)->
if op.creator isnt HB.getUserId() and this is that.elements
newNode = op.content.val()
right = op.next_cl
while right? and right.isDeleted()
right = right.next_cl
rightNode = null
if right.type isnt 'Delimiter'
rightNode = right.val().val()
dont_proxy ()->
that.xml.insertBefore newNode, rightNode
@elements.on 'delete', (event, op)->
del_op = op.deleted_by[0]
if del_op? and del_op.creator isnt HB.getUserId() and this is that.elements
deleted = op.content.val()
dont_proxy ()->
that.xml.removeChild deleted
@attributes.on ['add', 'update'], (event, property_name, op)->
if op.creator isnt HB.getUserId() and this is that.attributes
dont_proxy ()->
newval = op.val().val()
if newval?
that.xml.setAttribute(property_name, op.val().val())
else
that.xml.removeAttribute(property_name)
## Here are all methods that proxy the behavior of the xml
# you want to find a specific child element. Since they are carried by an Insert-Type, you want to find that Insert-Operation.
# @param child {DomElement} Dom element.
# @return {InsertType} This carries the XmlType that represents the DomElement (child). false if i couldn't find it.
#
findNode = (child)->
if not child?
throw new Error "you must specify a parameter!"
child = child._y
elem = that.elements.beginning.next_cl
while elem.type isnt 'Delimiter' and elem.content isnt child
elem = elem.next_cl
if elem.type is 'Delimiter'
false
else
elem
insertBefore = (insertedNode_s, adjacentNode)->
next = null
if adjacentNode?
next = findNode adjacentNode
prev = null
if next
prev = next.prev_cl
else
prev = @_y.elements.end.prev_cl
while prev.isDeleted()
prev = prev.prev_cl
inserted_nodes = null
if insertedNode_s.nodeType is insertedNode_s.DOCUMENT_FRAGMENT_NODE
child = insertedNode_s.lastChild
while child?
element = new XmlType undefined, undefined, undefined, undefined, child
HB.addOperation(element).execute()
that.elements.insertAfter prev, element
child = child.previousSibling
else
element = new XmlType undefined, undefined, undefined, undefined, insertedNode_s
HB.addOperation(element).execute()
that.elements.insertAfter prev, element
@xml._proxy 'insertBefore', insertBefore
@xml._proxy 'appendChild', insertBefore
@xml._proxy 'removeAttribute', (name)->
that.attributes.val(name, undefined)
@xml._proxy 'setAttribute', (name, value)->
that.attributes.val name, value
renewClassList = (newclass)->
dont_do_it = false
if newclass?
for elem in this
if newclass is elem
dont_do_it = true
value = Array.prototype.join.call this, " "
if newclass? and not dont_do_it
value += " "+newclass
that.attributes.val('class', value )
_proxy.call @xml.classList, 'add', renewClassList
_proxy.call @xml.classList, 'remove', renewClassList
@xml.__defineSetter__ 'className', (val)->
@setAttribute('class', val)
@xml.__defineGetter__ 'className', ()->
that.attributes.val('class')
@xml.__defineSetter__ 'textContent', (val)->
# remove all nodes
elem = that.xml.firstChild
while elem?
remove = elem
elem = elem.nextSibling
that.xml.removeChild remove
# insert word content
if val isnt ""
text_node = document.createTextNode val
that.xml.appendChild text_node
removeChild = (node)->
elem = findNode node
if not elem
throw new Error "You are only allowed to delete existing (direct) child elements!"
d = new types.Delete undefined, elem
HB.addOperation(d).execute()
node._y = null
@xml._proxy 'removeChild', removeChild
@xml._proxy 'replaceChild', (insertedNode, replacedNode)->
insertBefore.call this, insertedNode, replacedNode
removeChild.call this, replacedNode
val: (enforce = false)-> val: (enforce = false)->
if document? if document?
@@ -314,53 +95,3 @@ module.exports = (HB)->
} = json } = json
new XmlType uid, tagname, attributes, elements, undefined new XmlType uid, tagname, attributes, elements, undefined
#
# @nodoc
# Defines an object that is cannot be changed. You can use this to set an immutable string, or a number.
#
class TextNodeType extends types.ImmutableObject
#
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
# @param {Object} content
#
constructor: (uid, content)->
if content._y?
d = new types.Delete undefined, content._y
HB.addOperation(d).execute()
content._y = null
content._y = @
super uid, content
applyDelete: (op)->
if @insert_parent? and not @insert_parent.isDeleted()
@insert_parent.applyDelete op
else
super
type: "TextNodeType"
#
# Encode this operation in such a way that it can be parsed by remote peers.
#
_encode: ()->
json = {
'type': @type
'uid' : @getUid()
'content' : @content.textContent
}
json
parser['TextNodeType'] = (json)->
{
'uid' : uid
'content' : content
} = json
textnode = document.createTextNode content
new TextNodeType uid, textnode
types['XmlType'] = XmlType
json_types
+206 -25
View File
@@ -1,42 +1,72 @@
class YXml class YXml
constructor: (tagname, attributes = {})-> constructor: (tag_or_dom, attributes = {})->
@_xml = {} if not tag_or_dom?
#TODO: How to force the user to specify parameters? # nop
#if not tagname? else if tag_or_dom.constructor is String
# throw new Error "You must specify a tagname" tagname = tag_or_dom
@_xml.tagname = tagname @_xml = {}
if attributes.constructor isnt Object @_xml.children = []
throw new Error "The attributes must be specified as a Object" #TODO: How to force the user to specify parameters?
for a_name, a of attributes #if not tagname?
if a.constructor isnt String # throw new Error "You must specify a tagname"
throw new Error "The attributes must be of type String!" @_xml.tagname = tagname
@_xml.attributes = attributes if attributes.constructor isnt Object
@_xml.classes = {} throw new Error "The attributes must be specified as a Object"
_classes = @_xml.attributes.class for a_name, a of attributes
delete @_xml.attributes.class if a.constructor isnt String
if _classes? throw new Error "The attributes must be of type String!"
for c_name, c in _classes.split(" ") @_xml.attributes = attributes
if c.length > 0 @_xml.classes = {}
@_xml.classes[c_name] = c _classes = @_xml.attributes.class
undefined delete @_xml.attributes.class
if _classes?
for c_name, c in _classes.split(" ")
if c.length > 0
@_xml.classes[c_name] = c
undefined
else if tag_or_dom instanceof Element
@_dom = tag_or_dom
@_xml = {}
_name: "Xml" _name: "Xml"
_getModel: (Y, ops)-> _getModel: (Y, ops)->
if not @_model? if not @_model?
if @_dom?
@_xml.tagname = @_dom.tagName.toLowerCase()
@_xml.attributes = {}
@_xml.classes = {}
for attribute in @_dom.attributes
if attribute.name is "class"
for c in attribute.value.split(" ")
@_xml.classes[c] = true
else
@_xml.attributes[attribute.name] = attribute.value
@_xml.children = []
for child in @_dom.childNodes
if child.nodeType is child.TEXT_NODE
@_xml.children.push child.textContent
else
@_xml.children.push(new YXml(child))
@_model = new ops.MapManager(@).execute() @_model = new ops.MapManager(@).execute()
@_model.val("attributes", new Y.Object(@_xml.attributes)) @_model.val("attributes", new Y.Object(@_xml.attributes))
@_model.val("classes", new Y.Object(@_xml.classes)) @_model.val("classes", new Y.Object(@_xml.classes))
@_model.val("tagname", @_xml.tagname) @_model.val("tagname", @_xml.tagname)
@_model.val("children", new Y.List()) @_model.val("children", new Y.List(@_xml.children))
if @_xml.parent? if @_xml.parent?
@_model.val("parent", @_xml.parent) @_model.val("parent", @_xml.parent)
@_setModel @_model
if @_dom?
@getDom() # two way bind dom to this xml type
@_setModel @_model
@_model @_model
_setModel: (@_model)-> _setModel: (@_model)->
delete @_xml
@_model.observe (events)-> @_model.observe (events)->
for event in events for event in events
if event.name is "parent" and event.type isnt "add" if event.name is "parent" and event.type isnt "add"
@@ -47,8 +77,7 @@ class YXml
if c is @ if c is @
parent._model.val("children").delete i parent._model.val("children").delete i
break break
undefined delete @_xml
_setParent: (parent)-> _setParent: (parent)->
if parent instanceof YXml if parent instanceof YXml
@@ -260,6 +289,158 @@ class YXml
getChildren: ()-> getChildren: ()->
@_model.val("children").val() @_model.val("children").val()
getPosition: ()->
parent = @_model.val("parent")
if parent?
for c,i in parent._model.val("children").val()
if c is @
return i
throw new Error "This is not a child of its parent (should not happen in Y.Xml!)"
else
null
getDom: ()->
if not @_dom?
@_dom = document.createElement(@_model.val("tagname"))
# set the attributes _and_ the classes (@see .attr())
for attr_name, attr_value of @attr()
@_dom.setAttribute attr_name, attr_value
for child,i in @getChildren()
if child.constructor is String
dom = document.createTextNode child
else
dom = child.getDom()
@_dom.insertBefore dom
that = @
if (not @_dom._y_xml?)
@_dom._y_xml = @
initialize_proxies.call @
@_model.val("children").observe (events)->
for event in events
if event.type is "insert"
newNode = event.value.getDom()
children = that._dom.childNodes
if children.length > 0
rightNode = children[0]
else
rightNode = null
event.value._setParent that
dont_proxy ()->
that._dom.insertBefore newNode, rightNode
else if event.type is "delete"
deleted = event.oldValue.getDom()
dont_proxy ()->
that._dom.removeChild deleted
@_model.val("attributes").observe (events)->
for event in events
if event.type is "add" or event.type is "update"
newval = event.object.val(event.name)
dont_proxy ()->
that._dom.setAttribute event.name, newval
else if event.type is "delete"
dont_proxy ()->
that._dom.removeAttribute event.name
@_model.val("classes").observe (events)->
for event in events
if event.type is "add" or event.type is "update"
dont_proxy ()->
that._dom.classList.add event.name # classes are stored as the keys
else if event.type is "delete"
dont_proxy ()->
that._dom.classList.remove event.name
@_dom
proxies_are_initialized = false
# some dom implementations may call another dom.method that simulates the behavior of another.
# For example xml.insertChild(dom) , wich inserts an element at the end, and xml.insertAfter(dom,null) wich does the same
# But Y's proxy may be called only once!
proxy_token = false
dont_proxy = (f)->
proxy_token = true
try
f()
catch e
proxy_token = false
throw new Error e
proxy_token = false
initialize_proxies = ()->
_proxy = (f_name, f, source = Element.prototype)->
old_f = source[f_name]
source[f_name] = ()->
if (not @_y_xml?) or proxy_token
old_f.apply this, arguments
else
f.apply @_y_xml, arguments
that = this
@_dom.classList.add = (c)->
that.addClass c
@_dom.classList.remove = (c)->
that.removeClass c
@_dom.__defineSetter__ 'className', (val)->
that.attr('class', val)
@_dom.__defineGetter__ 'className', ()->
that.attr('class')
@_dom.__defineSetter__ 'textContent', (val)->
# remove all nodes
that.empty()
# insert word content
if val isnt ""
that.append val
if proxies_are_initialized
return
proxies_are_initialized = true
# the following methods are initialized on prototypes and therefore they need to be written only once!
insertBefore = (insertedNode_s, adjacentNode)->
if adjacentNode?
pos = adjacentNode._y_xml.getPosition()
else
pos = @getChildren().length
new_childs = []
if insertedNode_s.nodeType is insertedNode_s.DOCUMENT_FRAGMENT_NODE
child = insertedNode_s.firstChild
while child?
new_childs.push child
child = child.nextSibling
else
new_childs.push insertedNode_s
new_childs = new_childs.map (child)->
if child._y_xml?
child._y_xml
else if child.nodeType == child.TEXT_NODE
child.textContent
else
new YXml(child)
@_model.val("children").insertContents pos, new_childs
_proxy 'insertBefore', insertBefore
_proxy 'appendChild', insertBefore
_proxy 'removeAttribute', (name)->
@removeAttr name
_proxy 'setAttribute', (name, value)->
@attr name, value
removeChild = (node)->
node._y_xml.remove()
_proxy 'removeChild', removeChild, @_dom
replaceChild = (insertedNode, replacedNode)->
insertBefore.call this, insertedNode, replacedNode
removeChild.call this, replacedNode
_proxy 'replaceChild', replaceChild, @_dom
if window? if window?
if window.Y? if window.Y?
+222 -9
View File
@@ -4,6 +4,7 @@ should = chai.should()
sinon = require('sinon') sinon = require('sinon')
sinonChai = require('sinon-chai') sinonChai = require('sinon-chai')
_ = require("underscore") _ = require("underscore")
$ = require('jquery')
chai.use(sinonChai) chai.use(sinonChai)
@@ -27,7 +28,7 @@ class XmlTest extends Test
super new Y conn super new Y conn
initUsers: (u)-> initUsers: (u)->
u.val("xml",new Y.Xml("root")) u.val("xml",new Y.Xml("div"))
type: "XmlTest" type: "XmlTest"
@@ -175,7 +176,7 @@ describe "Y-Xml", ->
child2 = new Y.Xml("child2") child2 = new Y.Xml("child2")
@u1.append child @u1.append child
@u1.append child2 @u1.append child2
expect(@u1.toString()).to.equal("<root><child></child><child2></child2></root>") expect(@u1.toString()).to.equal("<div><child></child><child2></child2></div>")
@yTest.compareAll() @yTest.compareAll()
it "prepend", -> it "prepend", ->
@@ -183,31 +184,31 @@ describe "Y-Xml", ->
child2 = new Y.Xml("child2") child2 = new Y.Xml("child2")
@u1.prepend child2 @u1.prepend child2
@u1.prepend child @u1.prepend child
expect(@u1.toString()).to.equal("<root><child></child><child2></child2></root>") expect(@u1.toString()).to.equal("<div><child></child><child2></child2></div>")
@yTest.compareAll() @yTest.compareAll()
it "after", -> it "after", ->
child = new Y.Xml("child") child = new Y.Xml("child")
@u1.append child @u1.append child
child.after new Y.Xml("right-child") child.after new Y.Xml("right-child")
expect(@u1.toString()).to.equal("<root><child></child><right-child></right-child></root>") expect(@u1.toString()).to.equal("<div><child></child><right-child></right-child></div>")
@yTest.compareAll() @yTest.compareAll()
it "before", -> it "before", ->
child = new Y.Xml("child") child = new Y.Xml("child")
@u1.append child @u1.append child
child.before new Y.Xml("left-child") child.before new Y.Xml("left-child")
expect(@u1.toString()).to.equal("<root><left-child></left-child><child></child></root>") expect(@u1.toString()).to.equal("<div><left-child></left-child><child></child></div>")
@yTest.compareAll() @yTest.compareAll()
it "empty", -> it "empty", ->
child = new Y.Xml("child") child = new Y.Xml("child")
@u1.append child @u1.append child
child.before new Y.Xml("left-child") child.before new Y.Xml("left-child")
expect(@u1.toString()).to.equal("<root><left-child></left-child><child></child></root>") expect(@u1.toString()).to.equal("<div><left-child></left-child><child></child></div>")
@yTest.compareAll() @yTest.compareAll()
@u1.empty() @u1.empty()
expect(@u1.toString()).to.equal("<root></root>") expect(@u1.toString()).to.equal("<div></div>")
@yTest.compareAll() @yTest.compareAll()
it "remove", -> it "remove", ->
@@ -215,10 +216,10 @@ describe "Y-Xml", ->
child2 = new Y.Xml("child2") child2 = new Y.Xml("child2")
@u1.prepend child2 @u1.prepend child2
@u1.prepend child @u1.prepend child
expect(@u1.toString()).to.equal("<root><child></child><child2></child2></root>") expect(@u1.toString()).to.equal("<div><child></child><child2></child2></div>")
@yTest.compareAll() @yTest.compareAll()
child2.remove() child2.remove()
expect(@u1.toString()).to.equal("<root><child></child></root>") expect(@u1.toString()).to.equal("<div><child></child></div>")
it "removeAttr", -> it "removeAttr", ->
@u1.attr("dtrn", "stuff") @u1.attr("dtrn", "stuff")
@@ -258,4 +259,216 @@ describe "Y-Xml", ->
@u1.prepend(child) @u1.prepend(child)
expect(@u1.getChildren()[0]).to.equal(child) expect(@u1.getChildren()[0]).to.equal(child)
if not window?
describe "skip DOM tests (only in browser environment)", ->
it "", ->
else
describe "DOM binding ", ->
beforeEach (done)->
@dom = @u1.getDom()
@j = $(@dom)
done()
it "can transform to a new real Dom element", ->
expect(@dom).to.not.be.undefined
it "supports dom.insertBefore", ->
newdom = $("<p>dtrn</p>")[0]
newdom2 = $("<p>dtrn2</p>")[0]
@dom.insertBefore(newdom2, null)
@dom.insertBefore(newdom, newdom2)
expect(@u1+"").to.equal("<div><p>dtrn</p><p>dtrn2</p></div>")
expect(@dom.outerHTML).to.equal("<div><p>dtrn</p><p>dtrn2</p></div>")
it "supports dom.appendChild", ->
newdom = $("<p>dtrn</p>")[0]
@dom.appendChild(newdom)
expect(@u1+"").to.equal("<div><p>dtrn</p></div>")
it "supports dom.setAttribute", ->
@dom.setAttribute("test_attribute", "newVal")
expect(@u1.attr("test_attribute")).to.equal("newVal")
expect(@dom.getAttribute("test_attribute")).to.equal("newVal")
it "supports dom.removeAttribute", ->
@dom.setAttribute("test_attribute", "newVal")
expect(@u1.attr("test_attribute")).to.equal("newVal")
expect(@dom.getAttribute("test_attribute")).to.equal("newVal")
@dom.removeAttribute("test_attribute")
expect(@u1.attr("test_attribute")).to.be.undefined
expect(@dom.getAttribute("test_attribute")).to.be.undefined
it "supports dom.removeChild", ->
newdom = $("<p>dtrn</p>")[0]
@dom.appendChild(newdom)
expect(@u1+"").to.equal("<div><p>dtrn</p></div>")
expect(@dom.outerHTML).to.equal("<div><p>dtrn</p></div>")
@dom.removeChild(newdom)
expect(@dom.childNodes.length).to.equal(0)
expect(@u1.getChildren().length).to.equal(0)
it "supports dom.replaceChild", ->
dom = $("<p>dtrn</p>")[0]
@dom.appendChild(newdom)
expect(@u1+"").to.equal("<div><p>dtrn</p></div>")
expect(@dom.outerHTML).to.equal("<div><p>dtrn</p></div>")
newdom = $("<p>replaced</p>")[0]
@dom.replaceChild(dom,newdom)
expect(@dom.outerHTML).to.equal("<div><p>replaced</p></div>")
expect(@u1+"").to.equal("<div><p>replaced</p></div>")
it "supports dom.classList.add", ->
@dom.classList.add "classy"
@dom.classList.add "moreclassy"
expect(@u1.attr("class")).to.equal("classy moreclassy")
expect(@dom.getAttribute("class")).to.equal("classy moreclassy")
it "supports dom.textContent", ->
dom = $("<p>dtrn</p>")[0]
@dom.appendChild(newdom)
expect(@u1+"").to.equal("<div><p>dtrn</p></div>")
expect(@dom.outerHTML).to.equal("<div><p>dtrn</p></div>")
@dom.textContent = ""
expect(@u1+"").to.equal("<div></div>")
expect(@dom.outerHTML).to.equal("<div></div>")
it "suppports dom.textContent (non empty string)", ->
dom = $("<p>dtrn</p>")[0]
@dom.appendChild(newdom)
expect(@u1+"").to.equal("<div><p>dtrn</p></div>")
expect(@dom.outerHTML).to.equal("<div><p>dtrn</p></div>")
@dom.textContent = "stuff"
expect(@u1+"").to.equal("<div>stuff</div>")
expect(@dom.outerHTML).to.equal("<div>stuff</div>")
it "supports jquery.addClass", ->
@j.addClass("testy")
@j.addClass("testedy tested")
expect(@dom.getAttribute("class")).to.equal("testy testedy tested")
it "supports jquery.after", ->
d = $("<span></span>")
@dom.appendChild(d[0], null)
d.after("<div>after</div>")
expect(@dom.outerHTML).to.equal("<div><span></span><div>after</div></div>")
expect(@u1+"").to.equal("<div><span></span><div>after</div></div>")
it "supports jquery.append", ->
d = $("<span></span>")[0]
@j.append(d)
d = $("<div></div>")[0]
@dom.append(d)
expect(@dom.outerHTML).to.equal("<div><span></span><div></div></div>")
expect(@u1+"").to.equal("<div><span></span><div></div></div>")
it "supports jquery.appendTo", ->
$("<b>appendedTo</b>").appendTo(@dom)
$("p").appendTo(@dom)
expect(@dom.outerHTML).to.equal("<div><b>appendedTo</b><p></p></div>")
expect(@u1+"").to.equal("<div><b>appendedTo</b><p></p></div>")
it "supports jquery.before", ->
newdom = $("p")
$(@dom).append(newdom)
newdom.before("<div>before</div>")
expect(@dom.outerHTML).to.equal("<div><div>before</div><p></p></div>")
expect(@u1+"").to.equal("<div><div>before</div><p></p></div>")
it "supports jquery.detach", ->
d = $("p")
$j.append(d)
$j.detach("p")
expect(@dom.outerHTML).to.equal("<div></div>")
expect(@u1+"").to.equal("<div></div>")
it "supports jquery.empty", ->
d = $("<p />")
d.appendTo(@dom)
d = $("<div />")
d.appendTo(@dom)
@j.empty()
expect(@dom.outerHTML).to.equal("<div></div>")
expect(@u1+"").to.equal("<div></div>")
it "supports jquery.insertAfter", ->
d = $("span")
d.appendTo(@dom)
$("<p>after</p>").insertAfter(d)
expect(@dom.outerHTML).to.equal("<div><span></span><p>after</p></div>")
expect(@u1+"").to.equal("<div><span></span><p>after</p></div>")
it "supports jquery.insertBefore", ->
d = $("span")
d.appendTo(@j)
$("<p>after</p>").insertAfter(d)
expect(@dom.outerHTML).to.equal("<div><p>before</p><span></span></div>")
expect(@u1+"").to.equal("<div><p>before</p><span></span></div>")
it "supports jquery.prepend", ->
@j.prepend("<p>prepended2</p>")
@j.prepend("<p>prepended1</p>")
expect(@dom.outerHTML).to.equal("<div><p>prepended1</p><p>prepended2</p></div>")
expect(@u1+"").to.equal("<div><p>prepended1</p><p>prepended2</p></div>")
it "supports jquery.prependTo", ->
$("<p>prepended2</p>").prependTo(@j)
$("<p>prepended1</p>").prependTo(@j)
expect(@dom.outerHTML).to.equal("<div><p>prepended1</p><p>prepended2</p></div>")
expect(@u1+"").to.equal("<div><p>prepended1</p><p>prepended2</p></div>")
it "supports jquery.remove", ->
d = $("<div />")
d.prependTo(@j)
d.remove()
expect(@dom.outerHTML).to.equal("<div></div>")
expect(@u1+"").to.equal("<div></div>")
it "supports jquery.removeAttr", ->
@dom.setAttribute("test_attribute", "newVal")
expect(@u1.attr("test_attribute")).to.equal("newVal")
expect(@dom.getAttribute("test_attribute")).to.equal("newVal")
@j.removeAttr("test_attribute")
expect(@u1.attr("test_attribute")).to.be.undefined
expect(@j.attr("test_attribute")).to.be.undefined
it "supports jquery.removeClass", ->
@j.addClass("testy")
@j.addClass("testedy tested")
expect(@dom.getAttribute("class")).to.equal("testy testedy tested")
@j.removeClass("testedy")
expect(@dom.getAttribute("class")).to.equal("testy tested")
expect(@u1.hasClass("testedy")).to.be.false
it "supports jquery.attr", ->
@j.attr("atone", "yeah")
expect(@u1.attr("atone")).to.equal("yeah")
it "supports jquery.replaceAll", ->
$("<span>New span content </span>").replaceAll("#test_dom div")
@check()
it "supports jquery.replaceWith", ->
d = $("span")
@j.prepend(d)
d = $("span")
@j.prepend(d)
d = $("span")
@j.prepend(d)
d = @j.getElementsByTagName("span")
d.replaceWith("<div></div>")
expect(@dom.outerHTML).to.equal("<div><div></div><div></div><div></div></div>")
expect(@u1+"").to.equal("<div><div></div><div></div><div></div></div>")
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long