+ createDocumentNode: function(from) {
+ if(!(from instanceof Node)) {
+ if(from.text !== undefined) {
+ /* globals document */
+ from = document.createTextNode(from.text);
+ } else {
+ var node = $('<' + from.tagName + '>');
+
+ _.keys(from.attrs || {}).forEach(function(key) {
+ node.attr(key, from.attrs[key]);
+ });
+
+ from = node[0];
+ }
+ }
+ var Factory, typeMethods, typeTransformations;
+ if(from.nodeType === Node.TEXT_NODE) {
+ Factory = this.TextNodeFactory;
+ typeMethods = this._textNodeMethods;
+ typeTransformations = this._textNodeTransformations;
+ } else if(from.nodeType === Node.ELEMENT_NODE) {
+ Factory = this.ElementNodeFactory;
+ typeMethods = this._elementNodeMethods;
+ typeTransformations = this._elementNodeTransformations;
+ }
+ var toret = new Factory(from, this);
+ _.extend(toret, this._nodeMethods);
+ _.extend(toret, typeMethods);
+
+ _.extend(toret, this._nodeTransformations);
+ _.extend(toret, typeTransformations);
+
+ toret.__super__ = _.extend({}, this._nodeMethods, this._nodeTransformations);
+ _.keys(toret.__super__).forEach(function(key) {
+ toret.__super__[key] = _.bind(toret.__super__[key], toret);
+ });
+
+ return toret;
+ },
+
+ loadXML: function(xml, options) {
+ options = options || {};
+ this._defineDocumentProperties($(parseXML(xml)));
+ if(!options.silent) {
+ this.trigger('contentSet');
+ }
+ },
+
+ toXML: function() {
+ return this.root.toXML();
+ },
+
+ containsNode: function(node) {
+ return this.root && (node.nativeNode === this.root.nativeNode || node._$.parents().index(this.root._$) !== -1);
+ },
+
+ getSiblingParents: function(params) {
+ var parents1 = [params.node1].concat(params.node1.parents()).reverse(),
+ parents2 = [params.node2].concat(params.node2.parents()).reverse(),
+ noSiblingParents = null;
+
+ if(parents1.length === 0 || parents2.length === 0 || !(parents1[0].sameNode(parents2[0]))) {
+ return noSiblingParents;
+ }
+
+ var i;
+ for(i = 0; i < Math.min(parents1.length, parents2.length); i++) {
+ if(parents1[i].sameNode(parents2[i])) {
+ continue;
+ }
+ break;
+ }
+ return {node1: parents1[i], node2: parents2[i]};
+ },
+
+ trigger: function() {
+ Backbone.Events.trigger.apply(this, arguments);
+ },
+
+ getNodeInsertion: function(node) {
+ var insertion = {};
+ if(node instanceof DocumentNode) {
+ insertion.ofNode = node;
+ insertion.insertsNew = !this.containsNode(node);
+ } else {
+ insertion.ofNode = this.createDocumentNode(node);
+ insertion.insertsNew = true;