src/pyams_skin/resources/js/ext/tinymce/dev/classes/html/Node.js
changeset 557 bca7a7e058a3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_skin/resources/js/ext/tinymce/dev/classes/html/Node.js	Thu Feb 13 11:43:31 2020 +0100
@@ -0,0 +1,496 @@
+/**
+ * Node.js
+ *
+ * Copyright, Moxiecode Systems AB
+ * Released under LGPL License.
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+/**
+ * This class is a minimalistic implementation of a DOM like node used by the DomParser class.
+ *
+ * @example
+ * var node = new tinymce.html.Node('strong', 1);
+ * someRoot.append(node);
+ *
+ * @class tinymce.html.Node
+ * @version 3.4
+ */
+define("tinymce/html/Node", [], function() {
+	var whiteSpaceRegExp = /^[ \t\r\n]*$/, typeLookup = {
+		'#text': 3,
+		'#comment': 8,
+		'#cdata': 4,
+		'#pi': 7,
+		'#doctype': 10,
+		'#document-fragment': 11
+	};
+
+	// Walks the tree left/right
+	function walk(node, root_node, prev) {
+		var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next';
+
+		// Walk into nodes if it has a start
+		if (node[startName]) {
+			return node[startName];
+		}
+
+		// Return the sibling if it has one
+		if (node !== root_node) {
+			sibling = node[siblingName];
+
+			if (sibling) {
+				return sibling;
+			}
+
+			// Walk up the parents to look for siblings
+			for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) {
+				sibling = parent[siblingName];
+
+				if (sibling) {
+					return sibling;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Constructs a new Node instance.
+	 *
+	 * @constructor
+	 * @method Node
+	 * @param {String} name Name of the node type.
+	 * @param {Number} type Numeric type representing the node.
+	 */
+	function Node(name, type) {
+		this.name = name;
+		this.type = type;
+
+		if (type === 1) {
+			this.attributes = [];
+			this.attributes.map = {};
+		}
+	}
+
+	Node.prototype = {
+		/**
+		 * Replaces the current node with the specified one.
+		 *
+		 * @example
+		 * someNode.replace(someNewNode);
+		 *
+		 * @method replace
+		 * @param {tinymce.html.Node} node Node to replace the current node with.
+		 * @return {tinymce.html.Node} The old node that got replaced.
+		 */
+		replace: function(node) {
+			var self = this;
+
+			if (node.parent) {
+				node.remove();
+			}
+
+			self.insert(node, self);
+			self.remove();
+
+			return self;
+		},
+
+		/**
+		 * Gets/sets or removes an attribute by name.
+		 *
+		 * @example
+		 * someNode.attr("name", "value"); // Sets an attribute
+		 * console.log(someNode.attr("name")); // Gets an attribute
+		 * someNode.attr("name", null); // Removes an attribute
+		 *
+		 * @method attr
+		 * @param {String} name Attribute name to set or get.
+		 * @param {String} value Optional value to set.
+		 * @return {String/tinymce.html.Node} String or undefined on a get operation or the current node on a set operation.
+		 */
+		attr: function(name, value) {
+			var self = this, attrs, i, undef;
+
+			if (typeof name !== "string") {
+				for (i in name) {
+					self.attr(i, name[i]);
+				}
+
+				return self;
+			}
+
+			if ((attrs = self.attributes)) {
+				if (value !== undef) {
+					// Remove attribute
+					if (value === null) {
+						if (name in attrs.map) {
+							delete attrs.map[name];
+
+							i = attrs.length;
+							while (i--) {
+								if (attrs[i].name === name) {
+									attrs = attrs.splice(i, 1);
+									return self;
+								}
+							}
+						}
+
+						return self;
+					}
+
+					// Set attribute
+					if (name in attrs.map) {
+						// Set attribute
+						i = attrs.length;
+						while (i--) {
+							if (attrs[i].name === name) {
+								attrs[i].value = value;
+								break;
+							}
+						}
+					} else {
+						attrs.push({name: name, value: value});
+					}
+
+					attrs.map[name] = value;
+
+					return self;
+				} else {
+					return attrs.map[name];
+				}
+			}
+		},
+
+		/**
+		 * Does a shallow clones the node into a new node. It will also exclude id attributes since
+		 * there should only be one id per document.
+		 *
+		 * @example
+		 * var clonedNode = node.clone();
+		 *
+		 * @method clone
+		 * @return {tinymce.html.Node} New copy of the original node.
+		 */
+		clone: function() {
+			var self = this, clone = new Node(self.name, self.type), i, l, selfAttrs, selfAttr, cloneAttrs;
+
+			// Clone element attributes
+			if ((selfAttrs = self.attributes)) {
+				cloneAttrs = [];
+				cloneAttrs.map = {};
+
+				for (i = 0, l = selfAttrs.length; i < l; i++) {
+					selfAttr = selfAttrs[i];
+
+					// Clone everything except id
+					if (selfAttr.name !== 'id') {
+						cloneAttrs[cloneAttrs.length] = {name: selfAttr.name, value: selfAttr.value};
+						cloneAttrs.map[selfAttr.name] = selfAttr.value;
+					}
+				}
+
+				clone.attributes = cloneAttrs;
+			}
+
+			clone.value = self.value;
+			clone.shortEnded = self.shortEnded;
+
+			return clone;
+		},
+
+		/**
+		 * Wraps the node in in another node.
+		 *
+		 * @example
+		 * node.wrap(wrapperNode);
+		 *
+		 * @method wrap
+		 */
+		wrap: function(wrapper) {
+			var self = this;
+
+			self.parent.insert(wrapper, self);
+			wrapper.append(self);
+
+			return self;
+		},
+
+		/**
+		 * Unwraps the node in other words it removes the node but keeps the children.
+		 *
+		 * @example
+		 * node.unwrap();
+		 *
+		 * @method unwrap
+		 */
+		unwrap: function() {
+			var self = this, node, next;
+
+			for (node = self.firstChild; node;) {
+				next = node.next;
+				self.insert(node, self, true);
+				node = next;
+			}
+
+			self.remove();
+		},
+
+		/**
+		 * Removes the node from it's parent.
+		 *
+		 * @example
+		 * node.remove();
+		 *
+		 * @method remove
+		 * @return {tinymce.html.Node} Current node that got removed.
+		 */
+		remove: function() {
+			var self = this, parent = self.parent, next = self.next, prev = self.prev;
+
+			if (parent) {
+				if (parent.firstChild === self) {
+					parent.firstChild = next;
+
+					if (next) {
+						next.prev = null;
+					}
+				} else {
+					prev.next = next;
+				}
+
+				if (parent.lastChild === self) {
+					parent.lastChild = prev;
+
+					if (prev) {
+						prev.next = null;
+					}
+				} else {
+					next.prev = prev;
+				}
+
+				self.parent = self.next = self.prev = null;
+			}
+
+			return self;
+		},
+
+		/**
+		 * Appends a new node as a child of the current node.
+		 *
+		 * @example
+		 * node.append(someNode);
+		 *
+		 * @method append
+		 * @param {tinymce.html.Node} node Node to append as a child of the current one.
+		 * @return {tinymce.html.Node} The node that got appended.
+		 */
+		append: function(node) {
+			var self = this, last;
+
+			if (node.parent) {
+				node.remove();
+			}
+
+			last = self.lastChild;
+			if (last) {
+				last.next = node;
+				node.prev = last;
+				self.lastChild = node;
+			} else {
+				self.lastChild = self.firstChild = node;
+			}
+
+			node.parent = self;
+
+			return node;
+		},
+
+		/**
+		 * Inserts a node at a specific position as a child of the current node.
+		 *
+		 * @example
+		 * parentNode.insert(newChildNode, oldChildNode);
+		 *
+		 * @method insert
+		 * @param {tinymce.html.Node} node Node to insert as a child of the current node.
+		 * @param {tinymce.html.Node} ref_node Reference node to set node before/after.
+		 * @param {Boolean} before Optional state to insert the node before the reference node.
+		 * @return {tinymce.html.Node} The node that got inserted.
+		 */
+		insert: function(node, ref_node, before) {
+			var parent;
+
+			if (node.parent) {
+				node.remove();
+			}
+
+			parent = ref_node.parent || this;
+
+			if (before) {
+				if (ref_node === parent.firstChild) {
+					parent.firstChild = node;
+				} else {
+					ref_node.prev.next = node;
+				}
+
+				node.prev = ref_node.prev;
+				node.next = ref_node;
+				ref_node.prev = node;
+			} else {
+				if (ref_node === parent.lastChild) {
+					parent.lastChild = node;
+				} else {
+					ref_node.next.prev = node;
+				}
+
+				node.next = ref_node.next;
+				node.prev = ref_node;
+				ref_node.next = node;
+			}
+
+			node.parent = parent;
+
+			return node;
+		},
+
+		/**
+		 * Get all children by name.
+		 *
+		 * @method getAll
+		 * @param {String} name Name of the child nodes to collect.
+		 * @return {Array} Array with child nodes matchin the specified name.
+		 */
+		getAll: function(name) {
+			var self = this, node, collection = [];
+
+			for (node = self.firstChild; node; node = walk(node, self)) {
+				if (node.name === name) {
+					collection.push(node);
+				}
+			}
+
+			return collection;
+		},
+
+		/**
+		 * Removes all children of the current node.
+		 *
+		 * @method empty
+		 * @return {tinymce.html.Node} The current node that got cleared.
+		 */
+		empty: function() {
+			var self = this, nodes, i, node;
+
+			// Remove all children
+			if (self.firstChild) {
+				nodes = [];
+
+				// Collect the children
+				for (node = self.firstChild; node; node = walk(node, self)) {
+					nodes.push(node);
+				}
+
+				// Remove the children
+				i = nodes.length;
+				while (i--) {
+					node = nodes[i];
+					node.parent = node.firstChild = node.lastChild = node.next = node.prev = null;
+				}
+			}
+
+			self.firstChild = self.lastChild = null;
+
+			return self;
+		},
+
+		/**
+		 * Returns true/false if the node is to be considered empty or not.
+		 *
+		 * @example
+		 * node.isEmpty({img: true});
+		 * @method isEmpty
+		 * @param {Object} elements Name/value object with elements that are automatically treated as non empty elements.
+		 * @return {Boolean} true/false if the node is empty or not.
+		 */
+		isEmpty: function(elements) {
+			var self = this, node = self.firstChild, i, name;
+
+			if (node) {
+				do {
+					if (node.type === 1) {
+						// Ignore bogus elements
+						if (node.attributes.map['data-mce-bogus']) {
+							continue;
+						}
+
+						// Keep empty elements like <img />
+						if (elements[node.name]) {
+							return false;
+						}
+
+						// Keep bookmark nodes and name attribute like <a name="1"></a>
+						i = node.attributes.length;
+						while (i--) {
+							name = node.attributes[i].name;
+							if (name === "name" || name.indexOf('data-mce-bookmark') === 0) {
+								return false;
+							}
+						}
+					}
+
+					// Keep comments
+					if (node.type === 8) {
+						return false;
+					}
+
+					// Keep non whitespace text nodes
+					if ((node.type === 3 && !whiteSpaceRegExp.test(node.value))) {
+						return false;
+					}
+				} while ((node = walk(node, self)));
+			}
+
+			return true;
+		},
+
+		/**
+		 * Walks to the next or previous node and returns that node or null if it wasn't found.
+		 *
+		 * @method walk
+		 * @param {Boolean} prev Optional previous node state defaults to false.
+		 * @return {tinymce.html.Node} Node that is next to or previous of the current node.
+		 */
+		walk: function(prev) {
+			return walk(this, null, prev);
+		}
+	};
+
+	/**
+	 * Creates a node of a specific type.
+	 *
+	 * @static
+	 * @method create
+	 * @param {String} name Name of the node type to create for example "b" or "#text".
+	 * @param {Object} attrs Name/value collection of attributes that will be applied to elements.
+	 */
+	Node.create = function(name, attrs) {
+		var node, attrName;
+
+		// Create node
+		node = new Node(name, typeLookup[name] || 1);
+
+		// Add attributes if needed
+		if (attrs) {
+			for (attrName in attrs) {
+				node.attr(attrName, attrs[attrName]);
+			}
+		}
+
+		return node;
+	};
+
+	return Node;
+});