text:
/**
 * Utility class for various DOM manipulation and retrieval functions.
 *
 * @class tinymce.dom.DOMUtils
 * @example
 * // Add a class to an element by id in the page
 * tinymce.DOM.addClass('someid', 'someclass');
 *
 * // Add a class to an element by id inside the editor
 * tinymce.activeEditor.dom.addClass('someid', 'someclass');
 */
define("tinymce/dom/DOMUtils", [
	"tinymce/dom/Sizzle",
	"tinymce/dom/DomQuery",
	"tinymce/html/Styles",
	"tinymce/dom/EventUtils",
	"tinymce/dom/TreeWalker",
	"tinymce/dom/Range",
	"tinymce/html/Entities",
	"tinymce/Env",
	"tinymce/util/Tools",
	"tinymce/dom/StyleSheetLoader"
], function(Sizzle, $, Styles, EventUtils, TreeWalker, Range, Entities, Env, Tools, StyleSheetLoader) {
	// Shorten names
	var each = Tools.each, is = Tools.is, grep = Tools.grep, trim = Tools.trim;
	var isIE = Env.ie;
	var simpleSelectorRe = /^([a-z0-9],?)+$/i;
	var whiteSpaceRegExp = /^[ \t\r\n]*$/;

	function setupAttrHooks(domUtils, settings) {
		var attrHooks = {}, keepValues = settings.keep_values, keepUrlHook;

		keepUrlHook = {
			set: function($elm, value, name) {
				if (settings.url_converter) {
					value = settings.url_converter.call(settings.url_converter_scope || domUtils, value, name, $elm[0]);
				}

				$elm.attr('data-mce-' + name, value).attr(name, value);
			},

			get: function($elm, name) {
				return $elm.attr('data-mce-' + name) || $elm.attr(name);
			}
		};

		attrHooks = {
			style: {
				set: function($elm, value) {
					if (value !== null && typeof value === 'object') {
						$elm.css(value);
						return;
					}

					if (keepValues) {
						$elm.attr('data-mce-style', value);
					}

					$elm.attr('style', value);
				},

				get: function($elm) {
					var value = $elm.attr('data-mce-style') || $elm.attr('style');

					value = domUtils.serializeStyle(domUtils.parseStyle(value), $elm[0].nodeName);

					return value;
				}
			}
		};

		if (keepValues) {
			attrHooks.href = attrHooks.src = keepUrlHook;
		}

		return attrHooks;
	}

	function updateInternalStyleAttr(domUtils, $elm) {
		var value = $elm.attr('style');

		value = domUtils.serializeStyle(domUtils.parseStyle(value), $elm[0].nodeName);

		if (!value) {
			value = null;
		}

		$elm.attr('data-mce-style', value);
	}

	function nodeIndex(node, normalized) {
		var idx = 0, lastNodeType, nodeType;

		if (node) {
			for (lastNodeType = node.nodeType, node = node.previousSibling; node; node = node.previousSibling) {
				nodeType = node.nodeType;

				// Normalize text nodes
				if (normalized && nodeType == 3) {
					if (nodeType == lastNodeType || !node.nodeValue.length) {
						continue;
					}
				}
				idx++;
				lastNodeType = nodeType;
			}
		}

		return idx;
	}

	/**
	 * Constructs a new DOMUtils instance. Consult the Wiki for more details on settings etc for this class.
	 *
	 * @constructor
	 * @method DOMUtils
	 * @param {Document} doc Document reference to bind the utility class to.
	 * @param {settings} settings Optional settings collection.
	 */
	function DOMUtils(doc, settings) {
		var self = this, blockElementsMap;

		self.doc = doc;
		self.win = window;
		self.files = {};
		self.counter = 0;
		self.stdMode = !isIE || doc.documentMode >= 8;
		self.boxModel = !isIE || doc.compatMode == "CSS1Compat" || self.stdMode;
		self.styleSheetLoader = new StyleSheetLoader(doc);
		self.boundEvents = [];
		self.settings = settings = settings || {};
		self.schema = settings.schema;
		self.styles = new Styles({
			url_converter: settings.url_converter,
			url_converter_scope: settings.url_converter_scope
		}, settings.schema);

		self.fixDoc(doc);
		self.events = settings.ownEvents ? new EventUtils(settings.proxy) : EventUtils.Event;
		self.attrHooks = setupAttrHooks(self, settings);
		blockElementsMap = settings.schema ? settings.schema.getBlockElements() : {};
		self.$ = $.overrideDefaults(function() {
			return {
				context: doc,
				element: self.getRoot()
			};
		});

		/**
		 * Returns true/false if the specified element is a block element or not.
		 *
		 * @method isBlock
		 * @param {Node/String} node Element/Node to check.
		 * @return {Boolean} True/False state if the node is a block element or not.
		 */
		self.isBlock = function(node) {
			// Fix for #5446
			if (!node) {
				return false;
			}

			// This function is called in module pattern style since it might be executed with the wrong this scope
			var type = node.nodeType;

			// If it's a node then check the type and use the nodeName
			if (type) {
				return !!(type === 1 && blockElementsMap[node.nodeName]);
			}

			return !!blockElementsMap[node];
		};
	}

	DOMUtils.prototype = {
		$$: function(elm) {
			if (typeof elm == 'string') {
				elm = this.get(elm);
			}

			return this.$(elm);
		},

		root: null,

		fixDoc: function(doc) {
			var settings = this.settings, name;

			if (isIE && settings.schema) {
				// Add missing HTML 4/5 elements to IE
				('abbr article aside audio canvas ' +
				'details figcaption figure footer ' +
				'header hgroup mark menu meter nav ' +
				'output progress section summary ' +
				'time video').replace(/\w+/g, function(name) {
					doc.createElement(name);
				});

				// Create all custom elements
				for (name in settings.schema.getCustomElements()) {
					doc.createElement(name);
				}
			}
		},

		clone: function(node, deep) {
			var self = this, clone, doc;

			// TODO: Add feature detection here in the future
			if (!isIE || node.nodeType !== 1 || deep) {
				return node.cloneNode(deep);
			}

			doc = self.doc;

			// Make a HTML5 safe shallow copy
			if (!deep) {
				clone = doc.createElement(node.nodeName);

				// Copy attribs
				each(self.getAttribs(node), function(attr) {
					self.setAttrib(clone, attr.nodeName, self.getAttrib(node, attr.nodeName));
				});

				return clone;
			}

			return clone.firstChild;
		},

		/**
		 * Returns the root node of the document. This is normally the body but might be a DIV. Parents like getParent will not
		 * go above the point of this root node.
		 *
		 * @method getRoot
		 * @return {Element} Root element for the utility class.
		 */
		getRoot: function() {
			var self = this;

			return self.settings.root_element || self.doc.body;
		},

		/**
		 * Returns the viewport of the window.
		 *
		 * @method getViewPort
		 * @param {Window} win Optional window to get viewport of.
		 * @return {Object} Viewport object with fields x, y, w and h.
		 */
		getViewPort: function(win) {
			var doc, rootElm;

			win = !win ? this.win : win;
			doc = win.document;
			rootElm = this.boxModel ? doc.documentElement : doc.body;

			// Returns viewport size excluding scrollbars
			return {
				x: win.pageXOffset || rootElm.scrollLeft,
				y: win.pageYOffset || rootElm.scrollTop,
				w: win.innerWidth || rootElm.clientWidth,
				h: win.innerHeight || rootElm.clientHeight
			};
		},

		/**
		 * Returns the rectangle for a specific element.
		 *
		 * @method getRect
		 * @param {Element/String} elm Element object or element ID to get rectangle from.
		 * @return {object} Rectangle for specified element object with x, y, w, h fields.
		 */
		getRect: function(elm) {
			var self = this, pos, size;

			elm = self.get(elm);
			pos = self.getPos(elm);
			size = self.getSize(elm);

			return {
				x: pos.x, y: pos.y,
				w: size.w, h: size.h
			};
		},

		/**
		 * Returns the size dimensions of the specified element.
		 *
		 * @method getSize
		 * @param {Element/String} elm Element object or element ID to get rectangle from.
		 * @return {object} Rectangle for specified element object with w, h fields.
		 */
		getSize: function(elm) {
			var self = this, w, h;

			elm = self.get(elm);
			w = self.getStyle(elm, 'width');
			h = self.getStyle(elm, 'height');

			// Non pixel value, then force offset/clientWidth
			if (w.indexOf('px') === -1) {
				w = 0;
			}

			// Non pixel value, then force offset/clientWidth
			if (h.indexOf('px') === -1) {
				h = 0;
			}

			return {
				w: parseInt(w, 10) || elm.offsetWidth || elm.clientWidth,
				h: parseInt(h, 10) || elm.offsetHeight || elm.clientHeight
			};
		},

		/**
		 * Returns a node by the specified selector function. This function will
		 * loop through all parent nodes and call the specified function for each node.
		 * If the function then returns true indicating that it has found what it was looking for, the loop execution will then end
		 * and the node it found will be returned.
		 *
		 * @method getParent
		 * @param {Node/String} node DOM node to search parents on or ID string.
		 * @param {function} selector Selection function or CSS selector to execute on each node.
		 * @param {Node} root Optional root element, never go below this point.
		 * @return {Node} DOM Node or null if it wasn't found.
		 */
		getParent: function(node, selector, root) {
			return this.getParents(node, selector, root, false);
		},

		/**
		 * Returns a node list of all parents matching the specified selector function or pattern.
		 * If the function then returns true indicating that it has found what it was looking for and that node will be collected.
		 *
		 * @method getParents
		 * @param {Node/String} node DOM node to search parents on or ID string.
		 * @param {function} selector Selection function to execute on each node or CSS pattern.
		 * @param {Node} root Optional root element, never go below this point.
		 * @return {Array} Array of nodes or null if it wasn't found.
		 */
		getParents: function(node, selector, root, collect) {
			var self = this, selectorVal, result = [];

			node = self.get(node);
			collect = collect === undefined;

			// Default root on inline mode
			root = root || (self.getRoot().nodeName != 'BODY' ? self.getRoot().parentNode : null);

			// Wrap node name as func
			if (is(selector, 'string')) {
				selectorVal = selector;

				if (selector === '*') {
					selector = function(node) {
						return node.nodeType == 1;
					};
				} else {
					selector = function(node) {
						return self.is(node, selectorVal);
					};
				}
			}

			while (node) {
				if (node == root || !node.nodeType || node.nodeType === 9) {
					break;
				}

				if (!selector || selector(node)) {
					if (collect) {
						result.push(node);
					} else {
						return node;
					}
				}

				node = node.parentNode;
			}

			return collect ? result : null;
		},

		/**
		 * Returns the specified element by ID or the input element if it isn't a string.
		 *
		 * @method get
		 * @param {String/Element} n Element id to look for or element to just pass though.
		 * @return {Element} Element matching the specified id or null if it wasn't found.
		 */
		get: function(elm) {
			var name;

			if (elm && this.doc && typeof elm == 'string') {
				name = elm;
				elm = this.doc.getElementById(elm);

				// IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick
				if (elm && elm.id !== name) {
					return this.doc.getElementsByName(name)[1];
				}
			}

			return elm;
		},

		/**
		 * Returns the next node that matches selector or function
		 *
		 * @method getNext
		 * @param {Node} node Node to find siblings from.
		 * @param {String/function} selector Selector CSS expression or function.
		 * @return {Node} Next node item matching the selector or null if it wasn't found.
		 */
		getNext: function(node, selector) {
			return this._findSib(node, selector, 'nextSibling');
		},

		/**
		 * Returns the previous node that matches selector or function
		 *
		 * @method getPrev
		 * @param {Node} node Node to find siblings from.
		 * @param {String/function} selector Selector CSS expression or function.
		 * @return {Node} Previous node item matching the selector or null if it wasn't found.
		 */
		getPrev: function(node, selector) {
			return this._findSib(node, selector, 'previousSibling');
		},

		// #ifndef jquery

		/**
		 * Selects specific elements by a CSS level 3 pattern. For example "div#a1 p.test".
		 * This function is optimized for the most common patterns needed in TinyMCE but it also performs well enough
		 * on more complex patterns.
		 *
		 * @method select
		 * @param {String} selector CSS level 3 pattern to select/find elements by.
		 * @param {Object} scope Optional root element/scope element to search in.
		 * @return {Array} Array with all matched elements.
		 * @example
		 * // Adds a class to all paragraphs in the currently active editor
		 * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'someclass');
		 *
		 * // Adds a class to all spans that have the test class in the currently active editor
		 * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('span.test'), 'someclass')
		 */
		select: function(selector, scope) {
			var self = this;

			/*eslint new-cap:0 */
			return Sizzle(selector, self.get(scope) || self.settings.root_element || self.doc, []);
		},

		/**
		 * Returns true/false if the specified element matches the specified css pattern.
		 *
		 * @method is
		 * @param {Node/NodeList} elm DOM node to match or an array of nodes to match.
		 * @param {String} selector CSS pattern to match the element against.
		 */
		is: function(elm, selector) {
			var i;

			// If it isn't an array then try to do some simple selectors instead of Sizzle for to boost performance
			if (elm.length === undefined) {
				// Simple all selector
				if (selector === '*') {
					return elm.nodeType == 1;
				}

				// Simple selector just elements
				if (simpleSelectorRe.test(selector)) {
					selector = selector.toLowerCase().split(/,/);
					elm = elm.nodeName.toLowerCase();

					for (i = selector.length - 1; i >= 0; i--) {
						if (selector[i] == elm) {
							return true;
						}
					}

					return false;
				}
			}

			// Is non element
			if (elm.nodeType && elm.nodeType != 1) {
				return false;
			}

			var elms = elm.nodeType ? [elm] : elm;

			/*eslint new-cap:0 */
			return Sizzle(selector, elms[0].ownerDocument || elms[0], null, elms).length > 0;
		},

		// #endif

		/**
		 * Adds the specified element to another element or elements.
		 *
		 * @method add
		 * @param {String/Element/Array} parentElm Element id string, DOM node element or array of ids or elements to add to.
		 * @param {String/Element} name Name of new element to add or existing element to add.
		 * @param {Object} attrs Optional object collection with arguments to add to the new element(s).
		 * @param {String} html Optional inner HTML contents to add for each element.
		 * @param {Boolean} create Optional flag if the element should be created or added.
		 * @return {Element/Array} Element that got created, or an array of created elements if multiple input elements
		 * were passed in.
		 * @example
		 * // Adds a new paragraph to the end of the active editor
		 * tinymce.activeEditor.dom.add(tinymce.activeEditor.getBody(), 'p', {title: 'my title'}, 'Some content');
		 */
		add: function(parentElm, name, attrs, html, create) {
			var self = this;

			return this.run(parentElm, function(parentElm) {
				var newElm;

				newElm = is(name, 'string') ? self.doc.createElement(name) : name;
				self.setAttribs(newElm, attrs);

				if (html) {
					if (html.nodeType) {
						newElm.appendChild(html);
					} else {
						self.setHTML(newElm, html);
					}
				}

				return !create ? parentElm.appendChild(newElm) : newElm;
			});
		},

		/**
		 * Creates a new element.
		 *
		 * @method create
		 * @param {String} name Name of new element.
		 * @param {Object} attrs Optional object name/value collection with element attributes.
		 * @param {String} html Optional HTML string to set as inner HTML of the element.
		 * @return {Element} HTML DOM node element that got created.
		 * @example
		 * // Adds an element where the caret/selection is in the active editor
		 * var el = tinymce.activeEditor.dom.create('div', {id: 'test', 'class': 'myclass'}, 'some content');
		 * tinymce.activeEditor.selection.setNode(el);
		 */
		create: function(name, attrs, html) {
			return this.add(this.doc.createElement(name), name, attrs, html, 1);
		},

		/**
		 * Creates HTML string for element. The element will be closed unless an empty inner HTML string is passed in.
		 *
		 * @method createHTML
		 * @param {String} name Name of new element.
		 * @param {Object} attrs Optional object name/value collection with element attributes.
		 * @param {String} html Optional HTML string to set as inner HTML of the element.
		 * @return {String} String with new HTML element, for example: test.
		 * @example
		 * // Creates a html chunk and inserts it at the current selection/caret location
		 * tinymce.activeEditor.selection.setContent(tinymce.activeEditor.dom.createHTML('a', {href: 'test.html'}, 'some line'));
		 */
		createHTML: function(name, attrs, html) {
			var outHtml = '', key;

			outHtml += '<' + name;

			for (key in attrs) {
				if (attrs.hasOwnProperty(key) && attrs[key] !== null && typeof attrs[key] != 'undefined') {
					outHtml += ' ' + key + '="' + this.encode(attrs[key]) + '"';
				}
			}

			// A call to tinymce.is doesn't work for some odd reason on IE9 possible bug inside their JS runtime
			if (typeof html != "undefined") {
				return outHtml + '>' + html + '</' + name + '>';
			}

			return outHtml + ' />';
		},

		/**
		 * Creates a document fragment out of the specified HTML string.
		 *
		 * @method createFragment
		 * @param {String} html Html string to create fragment from.
		 * @return {DocumentFragment} Document fragment node.
		 */
		createFragment: function(html) {
			var frag, node, doc = this.doc, container;

			container = doc.createElement("div");
			frag = doc.createDocumentFragment();

			if (html) {
				container.innerHTML = html;
			}

			while ((node = container.firstChild)) {
				frag.appendChild(node);
			}

			return frag;
		},

		/**
		 * Removes/deletes the specified element(s) from the DOM.
		 *
		 * @method remove
		 * @param {String/Element/Array} node ID of element or DOM element object or array containing multiple elements/ids.
		 * @param {Boolean} keepChildren Optional state to keep children or not. If set to true all children will be
		 * placed at the location of the removed element.
		 * @return {Element/Array} HTML DOM element that got removed, or an array of removed elements if multiple input elements
		 * were passed in.
		 * @example
		 * // Removes all paragraphs in the active editor
		 * tinymce.activeEditor.dom.remove(tinymce.activeEditor.dom.select('p'));
		 *
		 * // Removes an element by id in the document
		 * tinymce.DOM.remove('mydiv');
		 */
		remove: function(node, keepChildren) {
			node = this.$$(node);

			if (keepChildren) {
				node.each(function() {
					var child;

					while ((child = this.firstChild)) {
						if (child.nodeType == 3 && child.data.length === 0) {
							this.removeChild(child);
						} else {
							this.parentNode.insertBefore(child, this);
						}
					}
				}).remove();
			} else {
				node.remove();
			}

			return node.length > 1 ? node.toArray() : node[0];
		},

		/**
		 * Sets the CSS style value on a HTML element. The name can be a camelcase string
		 * or the CSS style name like background-color.
		 *
		 * @method setStyle
		 * @param {String/Element/Array} elm HTML element/Array of elements to set CSS style value on.
		 * @param {String} name Name of the style value to set.
		 * @param {String} value Value to set on the style.
		 * @example
		 * // Sets a style value on all paragraphs in the currently active editor
		 * tinymce.activeEditor.dom.setStyle(tinymce.activeEditor.dom.select('p'), 'background-color', 'red');
		 *
		 * // Sets a style value to an element by id in the current document
		 * tinymce.DOM.setStyle('mydiv', 'background-color', 'red');
		 */
		setStyle: function(elm, name, value) {
			elm = this.$$(elm).css(name, value);

			if (this.settings.update_styles) {
				updateInternalStyleAttr(this, elm);
			}
		},

		/**
		 * Returns the current style or runtime/computed value of an element.
		 *
		 * @method getStyle
		 * @param {String/Element} elm HTML element or element id string to get style from.
		 * @param {String} name Style name to return.
		 * @param {Boolean} computed Computed style.
		 * @return {String} Current style or computed style value of an element.
		 */
		getStyle: function(elm, name, computed) {
			elm = this.$$(elm);

			if (computed) {
				return elm.css(name);
			}

			// Camelcase it, if needed
			name = name.replace(/-(\D)/g, function(a, b) {
				return b.toUpperCase();
			});

			if (name == 'float') {
				name = Env.ie && Env.ie < 12 ? 'styleFloat' : 'cssFloat';
			}

			return elm[0] && elm[0].style ? elm[0].style[name] : undefined;
		},

		/**
		 * Sets multiple styles on the specified element(s).
		 *
		 * @method setStyles
		 * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set styles on.
		 * @param {Object} styles Name/Value collection of style items to add to the element(s).
		 * @example
		 * // Sets styles on all paragraphs in the currently active editor
		 * tinymce.activeEditor.dom.setStyles(tinymce.activeEditor.dom.select('p'), {'background-color': 'red', 'color': 'green'});
		 *
		 * // Sets styles to an element by id in the current document
		 * tinymce.DOM.setStyles('mydiv', {'background-color': 'red', 'color': 'green'});
		 */
		setStyles: function(elm, styles) {
			elm = this.$$(elm).css(styles);

			if (this.settings.update_styles) {
				updateInternalStyleAttr(this, elm);
			}
		},

		/**
		 * Removes all attributes from an element or elements.
		 *
		 * @method removeAllAttribs
		 * @param {Element/String/Array} e DOM element, element id string or array of elements/ids to remove attributes from.
		 */
		removeAllAttribs: function(e) {
			return this.run(e, function(e) {
				var i, attrs = e.attributes;
				for (i = attrs.length - 1; i >= 0; i--) {
					e.removeAttributeNode(attrs.item(i));
				}
			});
		},

		/**
		 * Sets the specified attribute of an element or elements.
		 *
		 * @method setAttrib
		 * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set attribute on.
		 * @param {String} name Name of attribute to set.
		 * @param {String} value Value to set on the attribute - if this value is falsy like null, 0 or '' it will remove
		 * the attribute instead.
		 * @example
		 * // Sets class attribute on all paragraphs in the active editor
		 * tinymce.activeEditor.dom.setAttrib(tinymce.activeEditor.dom.select('p'), 'class', 'myclass');
		 *
		 * // Sets class attribute on a specific element in the current page
		 * tinymce.dom.setAttrib('mydiv', 'class', 'myclass');
		 */
		setAttrib: function(elm, name, value) {
			var self = this, originalValue, hook, settings = self.settings;

			if (value === '') {
				value = null;
			}

			elm = self.$$(elm);
			originalValue = elm.attr(name);

			if (!elm.length) {
				return;
			}

			hook = self.attrHooks[name];
			if (hook && hook.set) {
				hook.set(elm, value, name);
			} else {
				elm.attr(name, value);
			}

			if (originalValue != value && settings.onSetAttrib) {
				settings.onSetAttrib({
					attrElm: elm,
					attrName: name,
					attrValue: value
				});
			}
		},

		/**
		 * Sets two or more specified attributes of an element or elements.
		 *
		 * @method setAttribs
		 * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set attributes on.
		 * @param {Object} attrs Name/Value collection of attribute items to add to the element(s).
		 * @example
		 * // Sets class and title attributes on all paragraphs in the active editor
		 * tinymce.activeEditor.dom.setAttribs(tinymce.activeEditor.dom.select('p'), {'class': 'myclass', title: 'some title'});
		 *
		 * // Sets class and title attributes on a specific element in the current page
		 * tinymce.DOM.setAttribs('mydiv', {'class': 'myclass', title: 'some title'});
		 */
		setAttribs: function(elm, attrs) {
			var self = this;

			self.$$(elm).each(function(i, node) {
				each(attrs, function(value, name) {
					self.setAttrib(node, name, value);
				});
			});
		},

		/**
		 * Returns the specified attribute by name.
		 *
		 * @method getAttrib
		 * @param {String/Element} elm Element string id or DOM element to get attribute from.
		 * @param {String} name Name of attribute to get.
		 * @param {String} defaultVal Optional default value to return if the attribute didn't exist.
		 * @return {String} Attribute value string, default value or null if the attribute wasn't found.
		 */
		getAttrib: function(elm, name, defaultVal) {
			var self = this, hook, value;

			elm = self.$$(elm);

			if (elm.length) {
				hook = self.attrHooks[name];

				if (hook && hook.get) {
					value = hook.get(elm, name);
				} else {
					value = elm.attr(name);
				}
			}

			if (typeof value == 'undefined') {
				value = defaultVal || '';
			}

			return value;
		},

		/**
		 * Returns the absolute x, y position of a node. The position will be returned in an object with x, y fields.
		 *
		 * @method getPos
		 * @param {Element/String} elm HTML element or element id to get x, y position from.
		 * @param {Element} rootElm Optional root element to stop calculations at.
		 * @return {object} Absolute position of the specified element object with x, y fields.
		 */
		getPos: function(elm, rootElm) {
			var self = this, x = 0, y = 0, offsetParent, doc = self.doc, body = doc.body, pos;

			elm = self.get(elm);
			rootElm = rootElm || body;

			if (elm) {
				// Use getBoundingClientRect if it exists since it's faster than looping offset nodes
				// Fallback to offsetParent calculations if the body isn't static better since it stops at the body root
				if (rootElm === body && elm.getBoundingClientRect && $(body).css('position') === 'static') {
					pos = elm.getBoundingClientRect();
					rootElm = self.boxModel ? doc.documentElement : body;

					// Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit
					// Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position
					x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - rootElm.clientLeft;
					y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - rootElm.clientTop;

					return {x: x, y: y};
				}

				offsetParent = elm;
				while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
					x += offsetParent.offsetLeft || 0;
					y += offsetParent.offsetTop || 0;
					offsetParent = offsetParent.offsetParent;
				}

				offsetParent = elm.parentNode;
				while (offsetParent && offsetParent != rootElm && offsetParent.nodeType) {
					x -= offsetParent.scrollLeft || 0;
					y -= offsetParent.scrollTop || 0;
					offsetParent = offsetParent.parentNode;
				}
			}

			return {x: x, y: y};
		},

		/**
		 * Parses the specified style value into an object collection. This parser will also
		 * merge and remove any redundant items that browsers might have added. It will also convert non-hex
		 * colors to hex values. Urls inside the styles will also be converted to absolute/relative based on settings.
		 *
		 * @method parseStyle
		 * @param {String} cssText Style value to parse, for example: border:1px solid red;.
		 * @return {Object} Object representation of that style, for example: {border: '1px solid red'}
		 */
		parseStyle: function(cssText) {
			return this.styles.parse(cssText);
		},

		/**
		 * Serializes the specified style object into a string.
		 *
		 * @method serializeStyle
		 * @param {Object} styles Object to serialize as string, for example: {border: '1px solid red'}
		 * @param {String} name Optional element name.
		 * @return {String} String representation of the style object, for example: border: 1px solid red.
		 */
		serializeStyle: function(styles, name) {
			return this.styles.serialize(styles, name);
		},

		/**
		 * Adds a style element at the top of the document with the specified cssText content.
		 *
		 * @method addStyle
		 * @param {String} cssText CSS Text style to add to top of head of document.
		 */
		addStyle: function(cssText) {
			var self = this, doc = self.doc, head, styleElm;

			// Prevent inline from loading the same styles twice
			if (self !== DOMUtils.DOM && doc === document) {
				var addedStyles = DOMUtils.DOM.addedStyles;

				addedStyles = addedStyles || [];
				if (addedStyles[cssText]) {
					return;
				}

				addedStyles[cssText] = true;
				DOMUtils.DOM.addedStyles = addedStyles;
			}

			// Create style element if needed
			styleElm = doc.getElementById('mceDefaultStyles');
			if (!styleElm) {
				styleElm = doc.createElement('style');
				styleElm.id = 'mceDefaultStyles';
				styleElm.type = 'text/css';

				head = doc.getElementsByTagName('head')[0];
				if (head.firstChild) {
					head.insertBefore(styleElm, head.firstChild);
				} else {
					head.appendChild(styleElm);
				}
			}

			// Append style data to old or new style element
			if (styleElm.styleSheet) {
				styleElm.styleSheet.cssText += cssText;
			} else {
				styleElm.appendChild(doc.createTextNode(cssText));
			}
		},

		/**
		 * Imports/loads the specified CSS file into the document bound to the class.
		 *
		 * @method loadCSS
		 * @param {String} url URL to CSS file to load.
		 * @example
		 * // Loads a CSS file dynamically into the current document
		 * tinymce.DOM.loadCSS('somepath/some.css');
		 *
		 * // Loads a CSS file into the currently active editor instance
		 * tinymce.activeEditor.dom.loadCSS('somepath/some.css');
		 *
		 * // Loads a CSS file into an editor instance by id
		 * tinymce.get('someid').dom.loadCSS('somepath/some.css');
		 *
		 * // Loads multiple CSS files into the current document
		 * tinymce.DOM.loadCSS('somepath/some.css,somepath/someother.css');
		 */
		loadCSS: function(url) {
			var self = this, doc = self.doc, head;

			// Prevent inline from loading the same CSS file twice
			if (self !== DOMUtils.DOM && doc === document) {
				DOMUtils.DOM.loadCSS(url);
				return;
			}

			if (!url) {
				url = '';
			}

			head = doc.getElementsByTagName('head')[0];

			each(url.split(','), function(url) {
				var link;

				url = Tools._addCacheSuffix(url);

				if (self.files[url]) {
					return;
				}

				self.files[url] = true;
				link = self.create('link', {rel: 'stylesheet', href: url});

				// IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug
				// This fix seems to resolve that issue by recalcing the document once a stylesheet finishes loading
				// It's ugly but it seems to work fine.
				if (isIE && doc.documentMode && doc.recalc) {
					link.onload = function() {
						if (doc.recalc) {
							doc.recalc();
						}

						link.onload = null;
					};
				}

				head.appendChild(link);
			});
		},

		/**
		 * Adds a class to the specified element or elements.
		 *
		 * @method addClass
		 * @param {String/Element/Array} elm Element ID string or DOM element or array with elements or IDs.
		 * @param {String} cls Class name to add to each element.
		 * @return {String/Array} String with new class value or array with new class values for all elements.
		 * @example
		 * // Adds a class to all paragraphs in the active editor
		 * tinymce.activeEditor.dom.addClass(tinymce.activeEditor.dom.select('p'), 'myclass');
		 *
		 * // Adds a class to a specific element in the current page
		 * tinymce.DOM.addClass('mydiv', 'myclass');
		 */
		addClass: function(elm, cls) {
			this.$$(elm).addClass(cls);
		},

		/**
		 * Removes a class from the specified element or elements.
		 *
		 * @method removeClass
		 * @param {String/Element/Array} elm Element ID string or DOM element or array with elements or IDs.
		 * @param {String} cls Class name to remove from each element.
		 * @return {String/Array} String of remaining class name(s), or an array of strings if multiple input elements
		 * were passed in.
		 * @example
		 * // Removes a class from all paragraphs in the active editor
		 * tinymce.activeEditor.dom.removeClass(tinymce.activeEditor.dom.select('p'), 'myclass');
		 *
		 * // Removes a class from a specific element in the current page
		 * tinymce.DOM.removeClass('mydiv', 'myclass');
		 */
		removeClass: function(elm, cls) {
			this.toggleClass(elm, cls, false);
		},

		/**
		 * Returns true if the specified element has the specified class.
		 *
		 * @method hasClass
		 * @param {String/Element} elm HTML element or element id string to check CSS class on.
		 * @param {String} cls CSS class to check for.
		 * @return {Boolean} true/false if the specified element has the specified class.
		 */
		hasClass: function(elm, cls) {
			return this.$$(elm).hasClass(cls);
		},

		/**
		 * Toggles the specified class on/off.
		 *
		 * @method toggleClass
		 * @param {Element} elm Element to toggle class on.
		 * @param {[type]} cls Class to toggle on/off.
		 * @param {[type]} state Optional state to set.
		 */
		toggleClass: function(elm, cls, state) {
			this.$$(elm).toggleClass(cls, state).each(function() {
				if (this.className === '') {
					$(this).attr('class', null);
				}
			});
		},

		/**
		 * Shows the specified element(s) by ID by setting the "display" style.
		 *
		 * @method show
		 * @param {String/Element/Array} elm ID of DOM element or DOM element or array with elements or IDs to show.
		 */
		show: function(elm) {
			this.$$(elm).show();
		},

		/**
		 * Hides the specified element(s) by ID by setting the "display" style.
		 *
		 * @method hide
		 * @param {String/Element/Array} elm ID of DOM element or DOM element or array with elements or IDs to hide.
		 * @example
		 * // Hides an element by id in the document
		 * tinymce.DOM.hide('myid');
		 */
		hide: function(elm) {
			this.$$(elm).hide();
		},

		/**
		 * Returns true/false if the element is hidden or not by checking the "display" style.
		 *
		 * @method isHidden
		 * @param {String/Element} elm Id or element to check display state on.
		 * @return {Boolean} true/false if the element is hidden or not.
		 */
		isHidden: function(elm) {
			return this.$$(elm).css('display') == 'none';
		},

		/**
		 * Returns a unique id. This can be useful when generating elements on the fly.
		 * This method will not check if the element already exists.
		 *
		 * @method uniqueId
		 * @param {String} prefix Optional prefix to add in front of all ids - defaults to "mce_".
		 * @return {String} Unique id.
		 */
		uniqueId: function(prefix) {
			return (!prefix ? 'mce_' : prefix) + (this.counter++);
		},

		/**
		 * Sets the specified HTML content inside the element or elements. The HTML will first be processed. This means
		 * URLs will get converted, hex color values fixed etc. Check processHTML for details.
		 *
		 * @method setHTML
		 * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set HTML inside of.
		 * @param {String} html HTML content to set as inner HTML of the element.
		 * @example
		 * // Sets the inner HTML of all paragraphs in the active editor
		 * tinymce.activeEditor.dom.setHTML(tinymce.activeEditor.dom.select('p'), 'some inner html');
		 *
		 * // Sets the inner HTML of an element by id in the document
		 * tinymce.DOM.setHTML('mydiv', 'some inner html');
		 */
		setHTML: function(elm, html) {
			elm = this.$$(elm);

			if (isIE) {
				elm.each(function(i, target) {
					if (target.canHaveHTML === false) {
						return;
					}

					// Remove all child nodes, IE keeps empty text nodes in DOM
					while (target.firstChild) {
						target.removeChild(target.firstChild);
					}

					try {
						// IE will remove comments from the beginning
						// unless you padd the contents with something
						target.innerHTML = '
' + html;
						target.removeChild(target.firstChild);
					} catch (ex) {
						// IE sometimes produces an unknown runtime error on innerHTML if it's a div inside a p
						$('

').html('
' + html).contents().slice(1).appendTo(target);
					}

					return html;
				});
			} else {
				elm.html(html);
			}
		},

		/**
		 * Returns the outer HTML of an element.
		 *
		 * @method getOuterHTML
		 * @param {String/Element} elm Element ID or element object to get outer HTML from.
		 * @return {String} Outer HTML string.
		 * @example
		 * tinymce.DOM.getOuterHTML(editorElement);
		 * tinymce.activeEditor.getOuterHTML(tinymce.activeEditor.getBody());
		 */
		getOuterHTML: function(elm) {
			elm = this.get(elm);

			// Older FF doesn't have outerHTML 3.6 is still used by some orgaizations
			return elm.nodeType == 1 && "outerHTML" in elm ? elm.outerHTML : $('

').append($(elm).clone()).html();
		},

		/**
		 * Sets the specified outer HTML on an element or elements.
		 *
		 * @method setOuterHTML
		 * @param {Element/String/Array} elm DOM element, element id string or array of elements/ids to set outer HTML on.
		 * @param {Object} html HTML code to set as outer value for the element.
		 * @example
		 * // Sets the outer HTML of all paragraphs in the active editor
		 * tinymce.activeEditor.dom.setOuterHTML(tinymce.activeEditor.dom.select('p'), '
some html
');
		 *
		 * // Sets the outer HTML of an element by id in the document
		 * tinymce.DOM.setOuterHTML('mydiv', '
some html
');
		 */
		setOuterHTML: function(elm, html) {
			var self = this;

			self.$$(elm).each(function() {
				try {
					// Older FF doesn't have outerHTML 3.6 is still used by some organizations
					if ("outerHTML" in this) {
						this.outerHTML = html;
						return;
					}
				} catch (ex) {
					// Ignore
				}

				// OuterHTML for IE it sometimes produces an "unknown runtime error"
				self.remove($(this).html(html), true);
			});
		},

		/**
		 * Entity decodes a string. This method decodes any HTML entities, such as å.
		 *
		 * @method decode
		 * @param {String} s String to decode entities on.
		 * @return {String} Entity decoded string.
		 */
		decode: Entities.decode,

		/**
		 * Entity encodes a string. This method encodes the most common entities, such as <>"&.
		 *
		 * @method encode
		 * @param {String} text String to encode with entities.
		 * @return {String} Entity encoded string.
		 */
		encode: Entities.encodeAllRaw,

		/**
		 * Inserts an element after the reference element.
		 *
		 * @method insertAfter
		 * @param {Element} node Element to insert after the reference.
		 * @param {Element/String/Array} referenceNode Reference element, element id or array of elements to insert after.
		 * @return {Element/Array} Element that got added or an array with elements.
		 */
		insertAfter: function(node, referenceNode) {
			referenceNode = this.get(referenceNode);

			return this.run(node, function(node) {
				var parent, nextSibling;

				parent = referenceNode.parentNode;
				nextSibling = referenceNode.nextSibling;

				if (nextSibling) {
					parent.insertBefore(node, nextSibling);
				} else {
					parent.appendChild(node);
				}

				return node;
			});
		},

		/**
		 * Replaces the specified element or elements with the new element specified. The new element will
		 * be cloned if multiple input elements are passed in.
		 *
		 * @method replace
		 * @param {Element} newElm New element to replace old ones with.
		 * @param {Element/String/Array} oldElm Element DOM node, element id or array of elements or ids to replace.
		 * @param {Boolean} keepChildren Optional keep children state, if set to true child nodes from the old object will be added
		 * to new ones.
		 */
		replace: function(newElm, oldElm, keepChildren) {
			var self = this;

			return self.run(oldElm, function(oldElm) {
				if (is(oldElm, 'array')) {
					newElm = newElm.cloneNode(true);
				}

				if (keepChildren) {
					each(grep(oldElm.childNodes), function(node) {
						newElm.appendChild(node);
					});
				}

				return oldElm.parentNode.replaceChild(newElm, oldElm);
			});
		},

		/**
		 * Renames the specified element and keeps its attributes and children.
		 *
		 * @method rename
		 * @param {Element} elm Element to rename.
		 * @param {String} name Name of the new element.
		 * @return {Element} New element or the old element if it needed renaming.
		 */
		rename: function(elm, name) {
			var self = this, newElm;

			if (elm.nodeName != name.toUpperCase()) {
				// Rename block element
				newElm = self.create(name);

				// Copy attribs to new block
				each(self.getAttribs(elm), function(attrNode) {
					self.setAttrib(newElm, attrNode.nodeName, self.getAttrib(elm, attrNode.nodeName));
				});

				// Replace block
				self.replace(newElm, elm, 1);
			}

			return newElm || elm;
		},

		/**
		 * Find the common ancestor of two elements. This is a shorter method than using the DOM Range logic.
		 *
		 * @method findCommonAncestor
		 * @param {Element} a Element to find common ancestor of.
		 * @param {Element} b Element to find common ancestor of.
		 * @return {Element} Common ancestor element of the two input elements.
		 */
		findCommonAncestor: function(a, b) {
			var ps = a, pe;

			while (ps) {
				pe = b;

				while (pe && ps != pe) {
					pe = pe.parentNode;
				}

				if (ps == pe) {
					break;
				}

				ps = ps.parentNode;
			}

			if (!ps && a.ownerDocument) {
				return a.ownerDocument.documentElement;
			}

			return ps;
		},

		/**
		 * Parses the specified RGB color value and returns a hex version of that color.
		 *
		 * @method toHex
		 * @param {String} rgbVal RGB string value like rgb(1,2,3)
		 * @return {String} Hex version of that RGB value like #FF00FF.
		 */
		toHex: function(rgbVal) {
			return this.styles.toHex(Tools.trim(rgbVal));
		},

		/**
		 * Executes the specified function on the element by id or dom element node or array of elements/id.
		 *
		 * @method run
		 * @param {String/Element/Array} elm ID or DOM element object or array with ids or elements.
		 * @param {function} func Function to execute for each item.
		 * @param {Object} scope Optional scope to execute the function in.
		 * @return {Object/Array} Single object, or an array of objects if multiple input elements were passed in.
		 */
		run: function(elm, func, scope) {
			var self = this, result;

			if (typeof elm === 'string') {
				elm = self.get(elm);
			}

			if (!elm) {
				return false;
			}

			scope = scope || this;
			if (!elm.nodeType && (elm.length || elm.length === 0)) {
				result = [];

				each(elm, function(elm, i) {
					if (elm) {
						if (typeof elm == 'string') {
							elm = self.get(elm);
						}

						result.push(func.call(scope, elm, i));
					}
				});

				return result;
			}

			return func.call(scope, elm);
		},

		/**
		 * Returns a NodeList with attributes for the element.
		 *
		 * @method getAttribs
		 * @param {HTMLElement/string} elm Element node or string id to get attributes from.
		 * @return {NodeList} NodeList with attributes.
		 */
		getAttribs: function(elm) {
			var attrs;

			elm = this.get(elm);

			if (!elm) {
				return [];
			}

			if (isIE) {
				attrs = [];

				// Object will throw exception in IE
				if (elm.nodeName == 'OBJECT') {
					return elm.attributes;
				}

				// IE doesn't keep the selected attribute if you clone option elements
				if (elm.nodeName === 'OPTION' && this.getAttrib(elm, 'selected')) {
					attrs.push({specified: 1, nodeName: 'selected'});
				}

				// It's crazy that this is faster in IE but it's because it returns all attributes all the time
				var attrRegExp = /<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;
				elm.cloneNode(false).outerHTML.replace(attrRegExp, '').replace(/[\w:\-]+/gi, function(a) {
					attrs.push({specified: 1, nodeName: a});
				});

				return attrs;
			}

			return elm.attributes;
		},

		/**
		 * Returns true/false if the specified node is to be considered empty or not.
		 *
		 * @example
		 * tinymce.DOM.isEmpty(node, {img: true});
		 * @method isEmpty
		 * @param {Object} elements Optional 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(node, elements) {
			var self = this, i, attributes, type, walker, name, brCount = 0;

			node = node.firstChild;
			if (node) {
				walker = new TreeWalker(node, node.parentNode);
				elements = elements || (self.schema ? self.schema.getNonEmptyElements() : null);

				do {
					type = node.nodeType;

					if (type === 1) {
						// Ignore bogus elements
						var bogusVal = node.getAttribute('data-mce-bogus');
						if (bogusVal) {
							node = walker.next(bogusVal === 'all');
							continue;
						}

						// Keep empty elements like
						name = node.nodeName.toLowerCase();
						if (elements && elements[name]) {
							// Ignore single BR elements in blocks like

 or

							if (name === 'br') {
								brCount++;
								node = walker.next();
								continue;
							}

							return false;
						}

						// Keep elements with data-bookmark attributes or name attribute like
						attributes = self.getAttribs(node);
						i = attributes.length;
						while (i--) {
							name = attributes[i].nodeName;
							if (name === "name" || name === 'data-mce-bookmark') {
								return false;
							}
						}
					}

					// Keep comment nodes
					if (type == 8) {
						return false;
					}

					// Keep non whitespace text nodes
					if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue))) {
						return false;
					}

					node = walker.next();
				} while (node);
			}

			return brCount <= 1;
		},

		/**
		 * Creates a new DOM Range object. This will use the native DOM Range API if it's
		 * available. If it's not, it will fall back to the custom TinyMCE implementation.
		 *
		 * @method createRng
		 * @return {DOMRange} DOM Range object.
		 * @example
		 * var rng = tinymce.DOM.createRng();
		 * alert(rng.startContainer + "," + rng.startOffset);
		 */
		createRng: function() {
			var doc = this.doc;

			return doc.createRange ? doc.createRange() : new Range(this);
		},

		/**
		 * Returns the index of the specified node within its parent.
		 *
		 * @method nodeIndex
		 * @param {Node} node Node to look for.
		 * @param {boolean} normalized Optional true/false state if the index is what it would be after a normalization.
		 * @return {Number} Index of the specified node.
		 */
		nodeIndex: nodeIndex,

		/**
		 * Splits an element into two new elements and places the specified split
		 * element or elements between the new ones. For example splitting the paragraph at the bold element in
		 * this example
abcabc123
 would produce
abc
abc
123
.
		 *
		 * @method split
		 * @param {Element} parentElm Parent element to split.
		 * @param {Element} splitElm Element to split at.
		 * @param {Element} replacementElm Optional replacement element to replace the split element with.
		 * @return {Element} Returns the split element or the replacement element if that is specified.
		 */
		split: function(parentElm, splitElm, replacementElm) {
			var self = this, r = self.createRng(), bef, aft, pa;

			// W3C valid browsers tend to leave empty nodes to the left/right side of the contents - this makes sense
			// but we don't want that in our code since it serves no purpose for the end user
			// For example splitting this html at the bold element:
			//
text 1CHOPtext 2

			// would produce:
			//
text 1
CHOP
text 2

			// this function will then trim off empty edges and produce:
			//
text 1
CHOP
text 2

			function trimNode(node) {
				var i, children = node.childNodes, type = node.nodeType;

				function surroundedBySpans(node) {
					var previousIsSpan = node.previousSibling && node.previousSibling.nodeName == 'SPAN';
					var nextIsSpan = node.nextSibling && node.nextSibling.nodeName == 'SPAN';
					return previousIsSpan && nextIsSpan;
				}

				if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') {
					return;
				}

				for (i = children.length - 1; i >= 0; i--) {
					trimNode(children[i]);
				}

				if (type != 9) {
					// Keep non whitespace text nodes
					if (type == 3 && node.nodeValue.length > 0) {
						// If parent element isn't a block or there isn't any useful contents for example "

"
						// Also keep text nodes with only spaces if surrounded by spans.
						// eg. "
a b
" should keep space between a and b
						var trimmedLength = trim(node.nodeValue).length;
						if (!self.isBlock(node.parentNode) || trimmedLength > 0 || trimmedLength === 0 && surroundedBySpans(node)) {
							return;
						}
					} else if (type == 1) {
						// If the only child is a bookmark then move it up
						children = node.childNodes;

						// TODO fix this complex if
						if (children.length == 1 && children[0] && children[0].nodeType == 1 &&
							children[0].getAttribute('data-mce-type') == 'bookmark') {
							node.parentNode.insertBefore(children[0], node);
						}

						// Keep non empty elements or img, hr etc
						if (children.length || /^(br|hr|input|img)$/i.test(node.nodeName)) {
							return;
						}
					}

					self.remove(node);
				}

				return node;
			}

			if (parentElm && splitElm) {
				// Get before chunk
				r.setStart(parentElm.parentNode, self.nodeIndex(parentElm));
				r.setEnd(splitElm.parentNode, self.nodeIndex(splitElm));
				bef = r.extractContents();

				// Get after chunk
				r = self.createRng();
				r.setStart(splitElm.parentNode, self.nodeIndex(splitElm) + 1);
				r.setEnd(parentElm.parentNode, self.nodeIndex(parentElm) + 1);
				aft = r.extractContents();

				// Insert before chunk
				pa = parentElm.parentNode;
				pa.insertBefore(trimNode(bef), parentElm);

				// Insert middle chunk
				if (replacementElm) {
					pa.insertBefore(replacementElm, parentElm);
					//pa.replaceChild(replacementElm, splitElm);
				} else {
					pa.insertBefore(splitElm, parentElm);
				}

				// Insert after chunk
				pa.insertBefore(trimNode(aft), parentElm);
				self.remove(parentElm);

				return replacementElm || splitElm;
			}
		},

		/**
		 * Adds an event handler to the specified object.
		 *
		 * @method bind
		 * @param {Element/Document/Window/Array} target Target element to bind events to.
		 * handler to or an array of elements/ids/documents.
		 * @param {String} name Name of event handler to add, for example: click.
		 * @param {function} func Function to execute when the event occurs.
		 * @param {Object} scope Optional scope to execute the function in.
		 * @return {function} Function callback handler the same as the one passed in.
		 */
		bind: function(target, name, func, scope) {
			var self = this;

			if (Tools.isArray(target)) {
				var i = target.length;

				while (i--) {
					target[i] = self.bind(target[i], name, func, scope);
				}

				return target;
			}

			// Collect all window/document events bound by editor instance
			if (self.settings.collect && (target === self.doc || target === self.win)) {
				self.boundEvents.push([target, name, func, scope]);
			}

			return self.events.bind(target, name, func, scope || self);
		},

		/**
		 * Removes the specified event handler by name and function from an element or collection of elements.
		 *
		 * @method unbind
		 * @param {Element/Document/Window/Array} target Target element to unbind events on.
		 * @param {String} name Event handler name, for example: "click"
		 * @param {function} func Function to remove.
		 * @return {bool/Array} Bool state of true if the handler was removed, or an array of states if multiple input elements
		 * were passed in.
		 */
		unbind: function(target, name, func) {
			var self = this, i;

			if (Tools.isArray(target)) {
				i = target.length;

				while (i--) {
					target[i] = self.unbind(target[i], name, func);
				}

				return target;
			}

			// Remove any bound events matching the input
			if (self.boundEvents && (target === self.doc || target === self.win)) {
				i = self.boundEvents.length;

				while (i--) {
					var item = self.boundEvents[i];

					if (target == item[0] && (!name || name == item[1]) && (!func || func == item[2])) {
						this.events.unbind(item[0], item[1], item[2]);
					}
				}
			}

			return this.events.unbind(target, name, func);
		},

		/**
		 * Fires the specified event name with object on target.
		 *
		 * @method fire
		 * @param {Node/Document/Window} target Target element or object to fire event on.
		 * @param {String} name Name of the event to fire.
		 * @param {Object} evt Event object to send.
		 * @return {Event} Event object.
		 */
		fire: function(target, name, evt) {
			return this.events.fire(target, name, evt);
		},

		// Returns the content editable state of a node
		getContentEditable: function(node) {
			var contentEditable;

			// Check type
			if (!node || node.nodeType != 1) {
				return null;
			}

			// Check for fake content editable
			contentEditable = node.getAttribute("data-mce-contenteditable");
			if (contentEditable && contentEditable !== "inherit") {
				return contentEditable;
			}

			// Check for real content editable
			return node.contentEditable !== "inherit" ? node.contentEditable : null;
		},

		getContentEditableParent: function(node) {
			var root = this.getRoot(), state = null;

			for (; node && node !== root; node = node.parentNode) {
				state = this.getContentEditable(node);

				if (state !== null) {
					break;
				}
			}

			return state;
		},

		/**
		 * Destroys all internal references to the DOM to solve IE leak issues.
		 *
		 * @method destroy
		 */
		destroy: function() {
			var self = this;

			// Unbind all events bound to window/document by editor instance
			if (self.boundEvents) {
				var i = self.boundEvents.length;

				while (i--) {
					var item = self.boundEvents[i];
					this.events.unbind(item[0], item[1], item[2]);
				}

				self.boundEvents = null;
			}

			// Restore sizzle document to window.document
			// Since the current document might be removed producing "Permission denied" on IE see #6325
			if (Sizzle.setDocument) {
				Sizzle.setDocument();
			}

			self.win = self.doc = self.root = self.events = self.frag = null;
		},

		isChildOf: function(node, parent) {
			while (node) {
				if (parent === node) {
					return true;
				}

				node = node.parentNode;
			}

			return false;
		},

		// #ifdef debug

		dumpRng: function(r) {
			return (
				'startContainer: ' + r.startContainer.nodeName +
				', startOffset: ' + r.startOffset +
				', endContainer: ' + r.endContainer.nodeName +
				', endOffset: ' + r.endOffset
			);
		},

		// #endif

		_findSib: function(node, selector, name) {
			var self = this, func = selector;

			if (node) {
				// If expression make a function of it using is
				if (typeof func == 'string') {
					func = function(node) {
						return self.is(node, selector);
					};
				}

				// Loop all siblings
				for (node = node[name]; node; node = node[name]) {
					if (func(node)) {
						return node;
					}
				}
			}

			return null;
		}
	};

	/**
	 * Instance of DOMUtils for the current document.
	 *
	 * @static
	 * @property DOM
	 * @type tinymce.dom.DOMUtils
	 * @example
	 * // Example of how to add a class to some element by id
	 * tinymce.DOM.addClass('someid', 'someclass');
	 */
	DOMUtils.DOM = new DOMUtils(document);
	DOMUtils.nodeIndex = nodeIndex;

	return DOMUtils;
});


text:
define([
    'jquery',
    '../../js/components/blackout'
], function($, Blackout) {

describe('Toolkit.Blackout', function() {
    var element,
        blackout;

    before(function() {
        blackout = Blackout.instance();
        element = blackout.element;
    });

    describe('constructor()', function() {
        var el;

        beforeEach(function() {
            el = $('#toolkit-blackout-1');
        });

        it('should auto-create the element', function() {
            expect(el[0]).to.equal(element[0]);
        });

        it('should auto-create the loader element', function() {
            expect(el.find('.loader')[0]).to.equal(blackout.loader[0]);
        });

        it('should set the loading message', function() {
            expect(el.find('.loader-message').text()).to.equal('Loading...');
        });
    });

    describe('show()', function() {
        it('should reveal the element on the first show', function(done) {
            expect(element.css('display')).to.equal('none');
            expect(blackout.count).to.equal(0);

            blackout.show();

            setTimeout(function() {
                expect(element.css('display')).to.equal('block');
                expect(blackout.count).to.equal(1);

                done();
            }, 10);
        });

        it('should increase the count on each consecutive show', function() {
            expect(element.css('display')).to.equal('block');
            expect(blackout.count).to.equal(1);

            blackout.show();

            expect(element.css('display')).to.equal('block');
            expect(blackout.count).to.equal(2);

            blackout.show();

            expect(element.css('display')).to.equal('block');
            expect(blackout.count).to.equal(3);
        });
    });

    describe('hide()', function() {
        it('should decrease the count on each consecutive hide', function() {
            expect(element.css('display')).to.equal('block');
            expect(blackout.count).to.equal(3);

            blackout.hide();

            expect(element.css('display')).to.equal('block');
            expect(blackout.count).to.equal(2);

            blackout.hide();

            expect(element.css('display')).to.equal('block');
            expect(blackout.count).to.equal(1);
        });

        it('should conceal the element on the last show', function(done) {
            expect(element.css('display')).to.equal('block');
            expect(blackout.count).to.equal(1);

            blackout.hide();

            setTimeout(function() {
                expect(element.css('display')).to.equal('none');
                expect(blackout.count).to.equal(0);

                done();
            }, 10);
        });
    });

    describe('destroy()', function() {
        before(function() {
            blackout.destroy();
        });

        it('should delete the element', function() {
            expect($('#toolkit-blackout-1').length).to.equal(0);
        });
    });
});

});

redpajama_set_name: RedPajamaGithub


text:
{% extends "shop/base.html" %}
{% block content %}

Dummy content for testing

{% endblock %}


text:
const {Logger} = require('../utils');

module.exports = class {

  constructor(proc = process) {
    this.__exitCode = 0;
    this.testRunner = null;
    this.process = proc;
    this.finishCallback = null;

    this.process.on('exit', this.onExit.bind(this));
    this.process.on('uncaughtException', err => {
      this.uncaught(err);
    });

    this.process.on('unhandledRejection', this.unhandled.bind(this));
  }

  setTestRunner(testRunner) {
    this.testRunner = testRunner;

    return this;
  }

  setExitCode(code) {
    this.__exitCode = code;

    return this;
  }

  get exitCode() {
    return this.__exitCode;
  }

  onExit(code) {
    if (code > 0) {
      this.setExitCode(code);
    }

    this.exit();
  }

  unhandled(err) {
    Logger.warn(`unhandledRejection: ${err.message}`);
    this.uncaught(err);
  }

  async getCurrentPromise(err) {
    if (this.testRunner && this.testRunner.currentSuite) {
      this.testRunner.registerUncaughtErr(err);
      this.testRunner.currentSuite.emptyQueue();

      const {currentRunnable} = this.testRunner.currentSuite;
      if (currentRunnable) {
        await currentRunnable.abort(err);
      }

      await this.testRunner.closeOpenSessions();

      if (this.testRunner.publishReport) {
        this.testRunner.publishReport = false;
        await this.testRunner.reportResults();
      }
    } else {
      Logger.error(err);
    }
  }

  uncaught(err) {
    const WebDriver = require('./webdriver-server.js');

    this.getCurrentPromise(err)
      .then(_ => WebDriver.stopInstances())
      .then(_ => this.closeProcess(err));
  }

  closeProcess(err) {
    if (this.finishCallback) {
      this.finishCallback(err);
    }

    this.setExitCode(1).exit();
  }

  exit() {
    this.process.exit && this.process.exit(this.exitCode);

    return this;
  }
};


text:
<?php

use Base\Sessions as BaseSessions;

/**
 * Skeleton subclass for representing a row from the 'sessions' table.
 *
 *
 *
 * You should add additional methods to this class to meet the
 * application requirements.  This class will only be generated as
 * long as it does not already exist in the output directory.
 *
 */
class Sessions extends BaseSessions
{

}


text:
package com.google.gerrit.acceptance.api.plugin;

import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.common.RawInputUtil;
import com.google.gerrit.extensions.api.plugins.PluginApi;
import com.google.gerrit.extensions.api.plugins.Plugins.ListRequest;
import com.google.gerrit.extensions.common.InstallPluginInput;
import com.google.gerrit.extensions.common.PluginInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RawInput;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import java.util.List;
import org.junit.Test;

@NoHttpd
public class PluginIT extends AbstractDaemonTest {
  private static final String JS_PLUGIN = "Gerrit.install(function(self){});\n";
  private static final String HTML_PLUGIN =
      String.format("<dom-module id=\"test\"><script>%s</script></dom-module>", JS_PLUGIN);
  private static final RawInput JS_PLUGIN_CONTENT = RawInputUtil.create(JS_PLUGIN.getBytes(UTF_8));
  private static final RawInput HTML_PLUGIN_CONTENT =
      RawInputUtil.create(HTML_PLUGIN.getBytes(UTF_8));

  private static final ImmutableList<String> PLUGINS =
      ImmutableList.of(
          "plugin-a.js", "plugin-b.html", "plugin-c.js", "plugin-d.html", "plugin_e.js");

  @Test
  @GerritConfig(name = "plugins.allowRemoteAdmin", value = "true")
  public void pluginManagement() throws Exception {
    // No plugins are loaded
    assertThat(list().get()).isEmpty();
    assertThat(list().all().get()).isEmpty();

    PluginApi api;
    // Install all the plugins
    InstallPluginInput input = new InstallPluginInput();
    for (String plugin : PLUGINS) {
      input.raw = plugin.endsWith(".js") ? JS_PLUGIN_CONTENT : HTML_PLUGIN_CONTENT;
      api = gApi.plugins().install(plugin, input);
      assertThat(api).isNotNull();
      PluginInfo info = api.get();
      String name = pluginName(plugin);
      assertThat(info.id).isEqualTo(name);
      assertThat(info.version).isEqualTo(pluginVersion(plugin));
      assertThat(info.indexUrl).isEqualTo(String.format("plugins/%s/", name));
      assertThat(info.filename).isEqualTo(plugin);
      assertThat(info.disabled).isNull();
    }
    assertPlugins(list().get(), PLUGINS);

    // With pagination
    assertPlugins(list().start(1).limit(2).get(), PLUGINS.subList(1, 3));

    // With prefix
    assertPlugins(list().prefix("plugin-b").get(), ImmutableList.of("plugin-b.html"));
    assertPlugins(list().prefix("PLUGIN-").get(), ImmutableList.of());

    // With substring
    assertPlugins(list().substring("lugin-").get(), PLUGINS.subList(0, PLUGINS.size() - 1));
    assertPlugins(list().substring("lugin-").start(1).limit(2).get(), PLUGINS.subList(1, 3));

    // With regex
    assertPlugins(list().regex(".*in-b").get(), ImmutableList.of("plugin-b.html"));
    assertPlugins(list().regex("plugin-.*").get(), PLUGINS.subList(0, PLUGINS.size() - 1));
    assertPlugins(list().regex("plugin-.*").start(1).limit(2).get(), PLUGINS.subList(1, 3));

    // Invalid match combinations
    assertBadRequest(list().regex(".*in-b").substring("a"));
    assertBadRequest(list().regex(".*in-b").prefix("a"));
    assertBadRequest(list().substring(".*in-b").prefix("a"));

    // Disable
    api = gApi.plugins().name("plugin-a");
    api.disable();
    api = gApi.plugins().name("plugin-a");
    assertThat(api.get().disabled).isTrue();
    assertPlugins(list().get(), PLUGINS.subList(1, PLUGINS.size()));
    assertPlugins(list().all().get(), PLUGINS);

    // Enable
    api.enable();
    api = gApi.plugins().name("plugin-a");
    assertThat(api.get().disabled).isNull();
    assertPlugins(list().get(), PLUGINS);

    // Non-admin cannot disable
    setApiUser(user);
    try {
      gApi.plugins().name("plugin-a").disable();
      fail("Expected AuthException");
    } catch (AuthException expected) {
      // Expected
    }
  }

  @Test
  public void installNotAllowed() throws Exception {
    exception.expect(MethodNotAllowedException.class);
    exception.expectMessage("remote plugin administration is disabled");
    gApi.plugins().install("test.js", new InstallPluginInput());
  }

  @Test
  public void getNonExistingThrowsNotFound() throws Exception {
    exception.expect(ResourceNotFoundException.class);
    gApi.plugins().name("does-not-exist");
  }

  private ListRequest list() throws RestApiException {
    return gApi.plugins().list();
  }

  private void assertPlugins(List<PluginInfo> actual, List<String> expected) {
    List<String> _actual = actual.stream().map(p -> p.id).collect(toList());
    List<String> _expected = expected.stream().map(p -> pluginName(p)).collect(toList());
    assertThat(_actual).containsExactlyElementsIn(_expected);
  }

  private String pluginName(String plugin) {
    int dot = plugin.indexOf(".");
    assertThat(dot).isGreaterThan(0);
    return plugin.substring(0, dot);
  }

  private String pluginVersion(String plugin) {
    String name = pluginName(plugin);
    int dash = name.lastIndexOf("-");
    return dash > 0 ? name.substring(dash + 1) : "";
  }

  private void assertBadRequest(ListRequest req) throws Exception {
    try {
      req.get();
      fail("Expected BadRequestException");
    } catch (BadRequestException e) {
      // Expected
    }
  }
}


text:
<template name="sidebar">

      {{> UI.contentBlock }}

</template>


text:
<?php

namespace Lamudi\UseCaseBundle\Processor\Input;

use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation;

class FormInputProcessor implements InputProcessorInterface
{
    /**
     * @var FormFactoryInterface
     */
    private $formFactory;

    /**
     * @param FormFactoryInterface $formFactory
     */
    public function __construct(FormFactoryInterface $formFactory)
    {
        $this->formFactory = $formFactory;
    }

    /**
     * Populates the request object by having a Symfony form handle the HTTP request. By default it uses
     * the entire request object as a target for data from the form.
     * Available options:
     * - name - required. The name of the form that will handle the request.
     * - data_field - optional. If specified, instead of populating the request fields, the processor dumps
     *     all the form data into this field in the use case request as an associative array.
     *
     * @param object                 $request The Use Case Request object to be initialized.
     * @param HttpFoundation\Request $input   Symfony HTTP request object.
     * @param array                  $options An array of configuration options.
     *
     * @return object the Use Case Request object is returned for testability purposes.
     */
    public function initializeRequest($request, $input, $options = [])
    {
        if (!isset($options['name'])) {
            throw new \InvalidArgumentException();
        }

        if (isset($options['data_field'])) {
            $form = $this->formFactory->create($options['name']);
            $form->handleRequest($input);

            $fieldName = $options['data_field'];
            $request->$fieldName = $form->getData();
        } else {
            $form = $this->formFactory->create($options['name'], $request, ['data_class' => get_class($request)]);
            $form->handleRequest($input);
        }

        return $request;
    }
}


text:
module RutaHelper
end


text:
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');

const controller = require('./controller');
// 创建一个Koa对象表示web app本身
const app = new Koa();

//对于所有请求,app都调用该异步方法来处理请求
app.use(async (ctx, next) => {
    console.log(`${ctx.request.method} ${ctx.request.url}`);
    await next();
});

app.use(bodyParser());

app.use(controller());

app.listen(4000);
console.log('app started at port 4000');


text:
#include <linux/export.h>
#include "gigaset.h"

void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
{
}
EXPORT_SYMBOL_GPL(gigaset_skb_sent);

void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
{
}
EXPORT_SYMBOL_GPL(gigaset_skb_rcvd);

void gigaset_isdn_rcv_err(struct bc_state *bcs)
{
}
EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err);

int gigaset_isdn_icall(struct at_state_t *at_state)
{
	return ICALL_IGNORE;
}

void gigaset_isdn_connD(struct bc_state *bcs)
{
}

void gigaset_isdn_hupD(struct bc_state *bcs)
{
}

void gigaset_isdn_connB(struct bc_state *bcs)
{
}

void gigaset_isdn_hupB(struct bc_state *bcs)
{
}

void gigaset_isdn_start(struct cardstate *cs)
{
}

void gigaset_isdn_stop(struct cardstate *cs)
{
}

int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
{
	return 1;
}

void gigaset_isdn_unregdev(struct cardstate *cs)
{
}

void gigaset_isdn_regdrv(void)
{
	pr_info("no ISDN subsystem interface\n");
}

void gigaset_isdn_unregdrv(void)
{
}


text:
<?php

$config = [
    'params' => [],

    'on beforeRequest' => function ($event) {
         \Yii::setAlias('template', '@app/views');
    },

    'components' =>
    [
        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'cookieValidationKey' => 'skeeks2',
        ],

        'user' =>
        [
            'identityClass' => 'common\models\User',
            /*'identityCookie' => [
                'name' => '_identity',
                'httpOnly' => true,
                'domain' => '.cms.skeeks.com'
            ]*/
        ],
    ]
];

return $config;


text:
package org.kd.ssh.base.dao;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.kd.ssh.annotation.HpField;
import org.kd.ssh.annotation.HpIsDeleteField;
import org.kd.ssh.annotation.model.BaseModel;
import org.kd.ssh.annotation.model.HpFieldModel;
import org.kd.ssh.annotation.model.HpIsDeleteFieldModel;
import org.kd.ssh.util.HpHqlUtil;
import org.kd.ssh.util.SortList;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

@SuppressWarnings("all")
public class BaseDaoImpl<T> implements BaseDao<T>

{

	private T model;

	private List<HpFieldModel> hpFieldModelList = new ArrayList<HpFieldModel>();

	private HpIsDeleteFieldModel hpIsDeleteFieldModel;

	public BaseDaoImpl() {
		try {

			// java 高级编程思想----> 反射思想 hibernate spring Struts2

			ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
			Class<T> clazz = (Class<T>) type.getActualTypeArguments()[0];
			model = clazz.newInstance();
			setHpFieldModel(clazz);// 设置注解
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Resource
	SessionFactory sessionFactory;

	@Override
	public void save(T model) {
		getHibernateSession().save(model);
	}

	@Override
	public void delete(Integer id) {
		Object obj = getById(id);
		if (obj != null) {
			getHibernateSession().delete(obj);
		} else {
			 throw new RuntimeException("id no exist--> id 不存在");
			// System.out.println("id no exist--> id 不存在");
			// log.error("id no exist--> id 不存在");
		}

	}

	@Override
	public void delete(String id) {
		Object obj = getById(id);
		if (obj != null) {
			getHibernateSession().delete(obj);
		} else {
			throw new RuntimeException("id no exist--> id 不存在");
			// System.out.println("id no exist--> id 不存在");
			// log.error("id no exist--> id 不存在");
		}

	}

	@Override
	public void update(T model) {
		getHibernateSession().update(model);
	}

	@Override
	public List<T> queryAllList() {
		String whereHql = getWhereHql();
		String orderHql = getOrderByHql();
		return getHibernateSession().createQuery("FROM " + model.getClass().getSimpleName() + whereHql + orderHql)
				.list();
	}

	@Override
	public T getById(Integer id) {
		return (T) getHibernateSession().get(model.getClass(), id);
	}

	@Override
	public T getById(String id) {
		return (T) getHibernateSession().get(model.getClass(), id);
	}

	@Override
	public Session getHibernateSession() {
		return sessionFactory.getCurrentSession();

	}

	@Override
	public List<T> queryPageList(Integer pageNum, Integer pageSize) {
		String whereHql = getWhereHql();
		String orderHql = getOrderByHql();
		return getHibernateSession().createQuery("FROM " + model.getClass().getSimpleName() + whereHql + orderHql)
				.setFirstResult((pageNum - 1) * pageSize).setMaxResults(pageSize).list();
	}

	@Override
	public List<T> queryParamsAllList(String whereSql, Map<String, Object> map) {
		Query query = getHibernateSession().createQuery("FROM " + model.getClass().getSimpleName() + " " + whereSql);
		int index = 0;
		for (Entry<String, Object> item : map.entrySet()) {
			query.setParameter(index, item.getValue());
			index++;
		}
		return query.list();
	}

	@Override
	public List<T> queryPageParamsList(Integer pageNum, Integer pageSize, String whereSql, Map<String, Object> map) {
		Query query = getHibernateSession().createQuery("FROM " + model.getClass().getSimpleName() + " " + whereSql);
		int index = 0;
		for (Entry<String, Object> item : map.entrySet()) {
			query.setParameter(index, item.getValue());
			index++;
		}
		return query.setFirstResult((pageNum - 1) * pageSize).setMaxResults(pageSize).list();
	}

	@Override
	public Long getCount() {
		Long count=null;
		if (hpIsDeleteFieldModel == null) {
			count=(Long) getHibernateSession().createQuery("Select count(*) FROM " + model.getClass().getSimpleName())
			.uniqueResult();
		}else{
			String whereHql = getWhereHql();
			count=(Long) getHibernateSession().createQuery("Select count(*) FROM " + model.getClass().getSimpleName()+whereHql)
			.uniqueResult();
		}
		return count;
	}

	@Override
	public Long getWhereHqlCount(String whereHql,Map<String, Object> map) {
		Query query = getHibernateSession().createQuery("Select count(*) FROM " + model.getClass().getSimpleName()+whereHql);
		int index = 0;
		for (Entry<String, Object> item : map.entrySet()) {
			query.setParameter(index, item.getValue());
			index++;
		}
		return (Long) query.uniqueResult();
	}

	@Override
	public void updateDelete(Integer id) {
		if (hpIsDeleteFieldModel == null) {
			// hpIsDeleteField 注解不存在
			throw new RuntimeException("not hpIsDeleteField  annotation no exist");
		}
		T t = getById(id);
		try {
			if (t.getClass().getSuperclass().getSimpleName().equals("Object")) {
				Method method = t.getClass().getDeclaredMethod(
						HpHqlUtil.getFieldMethod("set", hpIsDeleteFieldModel.getFieldName()), Integer.class);
				method.invoke(t, hpIsDeleteFieldModel.getFieldValue());
			}else{
				// 继承父类model的情况
				Method method = t.getClass().getSuperclass().getDeclaredMethod(
						HpHqlUtil.getFieldMethod("set", hpIsDeleteFieldModel.getFieldName()), Integer.class);
				method.invoke(t, hpIsDeleteFieldModel.getAlreadyDeleteValue());
			}
			getHibernateSession().update(t);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public void updateDelete(String id) {
		if (hpIsDeleteFieldModel == null) {
			// hpIsDeleteField 注解不存在
			throw new RuntimeException("not hpIsDeleteField  annotation no exist");
		}
		T t = getById(id);
		try {
			if (t.getClass().getSuperclass().getSimpleName().equals("Object")) {
				Method method = t.getClass().getDeclaredMethod(
						HpHqlUtil.getFieldMethod("set", hpIsDeleteFieldModel.getFieldName()), String.class);
				method.invoke(t, hpIsDeleteFieldModel.getFieldValue());
			}else{
				// 继承父类model的情况
				Method method = t.getClass().getSuperclass().getDeclaredMethod(
						HpHqlUtil.getFieldMethod("set", hpIsDeleteFieldModel.getFieldName()), String.class);
				method.invoke(t, hpIsDeleteFieldModel.getAlreadyDeleteValue());
			}
			getHibernateSession().update(t);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	// 设置 注解字段实体类
	public void setHpFieldModel(Class<T> clazz) {
		Field[] fields = clazz.getDeclaredFields();
		for (Field f : fields) {
			// 获取字段中包含HpField的注解
			HpField hpField = f.getAnnotation(HpField.class);
			if (hpField != null) {
				hpFieldModelList.add(new HpFieldModel(f.getName(), hpField.order(), hpField.orderIndex()));
			}
			// 获取字段中包含HpIsDeleteField的注解
			HpIsDeleteField isDeleteField = f.getAnnotation(HpIsDeleteField.class);
			if (isDeleteField != null) {
				if (StringUtils.isEmpty(isDeleteField.isDeleteField())) {
					hpIsDeleteFieldModel = new HpIsDeleteFieldModel(f.getName(), isDeleteField.isDeleteValue(),isDeleteField.alreadyDeleteValue());
				}else{
					hpIsDeleteFieldModel = new HpIsDeleteFieldModel(isDeleteField.isDeleteField(), isDeleteField.isDeleteValue(),isDeleteField.alreadyDeleteValue());
				}
			}
		}

		// 继承 baseModel 情况  model instanceof BaseModel
		if (!clazz.getSuperclass().getSimpleName().equals("Object")) {
			Field[] parentFieds = clazz.getSuperclass().getDeclaredFields();
			for (Field f : parentFieds) {
				// 获取字段中包含HpIsDeleteField的注解
				HpIsDeleteField isDeleteField = f.getAnnotation(HpIsDeleteField.class);
				if (isDeleteField != null) {
					if (StringUtils.isEmpty(isDeleteField.isDeleteField())) {
						hpIsDeleteFieldModel = new HpIsDeleteFieldModel(f.getName(),
								isDeleteField.isDeleteValue(),isDeleteField.alreadyDeleteValue());
					}else{
						hpIsDeleteFieldModel = new HpIsDeleteFieldModel(isDeleteField.isDeleteField(), isDeleteField.isDeleteValue(),isDeleteField.alreadyDeleteValue());
					}
				}
			}
		}

	}

	// 获取whereHql语句
	public String getWhereHql() {
		String whereHql = "";
		if (hpIsDeleteFieldModel != null) {
			whereHql += " where 1=1 and " + hpIsDeleteFieldModel.getFieldName() + "="
					+ hpIsDeleteFieldModel.getFieldValue();
		}
		return whereHql;
	}

	// 获取排序hql语句
	public String getOrderByHql() {
		String orderHql = "";
		if (!CollectionUtils.isEmpty(hpFieldModelList)) {
			orderHql = " order by ";
			// 先排序
			SortList.sort(hpFieldModelList, "orderIndex", true);
			// 再拼接
			StringBuilder sbd = new StringBuilder();
			for (HpFieldModel hpFieldModel : hpFieldModelList) {
				sbd.append(hpFieldModel.getFieldName());
				sbd.append(" ");
				sbd.append(hpFieldModel.getOrder());
				sbd.append(",");
			}

			orderHql = orderHql + sbd.substring(0, sbd.length() - 1);
		}
		return orderHql;
	}

}


text:
namespace Foundation.Data.Hibernate
{
    /// <summary>
    /// An error has occurred when trying to use the NHibernate data provider.
    /// </summary>
    public class HibernateDataServicesProviderException : BaseException
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="HibernateDataServicesProviderException"/> class.
        /// </summary>
        /// <param name="message">The formattable error message.</param>
        /// <param name="args">The args to format the <paramref name="message"/> with.</param>
        public HibernateDataServicesProviderException(string message, params object[] args) : base(message, args) {}
    }
}


text:
[![Build Status](https://travis-ci.org/jlagneau/demo-spa.svg?branch=master)](https://travis-ci.org/jlagneau/demo-spa)

Demo of a single page application using a REST API (https://github.com/jlagneau/demo-rest-api)

---

## Install the Polymer-CLI

First, make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed. Then run `polymer serve` to serve your application locally.

## Viewing Your Application

```
$ polymer serve
```

## Building Your Application

```
$ polymer build
```

This will create a `build/` folder with `bundled/` and `unbundled/` sub-folders
containing a bundled (Vulcanized) and unbundled builds, both run through HTML,
CSS, and JS optimizers.

You can serve the built versions by giving `polymer serve` a folder to serve
from:

```
$ polymer serve build/bundled
```

## Running Tests

```
$ polymer test
```

Your application is already set up to be tested via [web-component-tester](https://github.com/Polymer/web-component-tester). Run `polymer test` to run your application's test suite locally.