src/pyams_skin/resources/js/ext/tinymce/dev/classes/dom/DomQuery.js
changeset 69 a361355b55c7
equal deleted inserted replaced
68:fd8fb93e1b6a 69:a361355b55c7
       
     1 /**
       
     2  * DomQuery.js
       
     3  *
       
     4  * Copyright, Moxiecode Systems AB
       
     5  * Released under LGPL License.
       
     6  *
       
     7  * License: http://www.tinymce.com/license
       
     8  * Contributing: http://www.tinymce.com/contributing
       
     9  */
       
    10 
       
    11 /**
       
    12  * This class mimics most of the jQuery API:
       
    13  *
       
    14  * This is whats currently implemented:
       
    15  * - Utility functions
       
    16  * - DOM traversial
       
    17  * - DOM manipulation
       
    18  * - Event binding
       
    19  *
       
    20  * This is not currently implemented:
       
    21  * - Dimension
       
    22  * - Ajax
       
    23  * - Animation
       
    24  * - Advanced chaining
       
    25  *
       
    26  * @example
       
    27  * var $ = tinymce.dom.DomQuery;
       
    28  * $('p').attr('attr', 'value').addClass('class');
       
    29  *
       
    30  * @class tinymce.dom.DomQuery
       
    31  */
       
    32 define("tinymce/dom/DomQuery", [
       
    33 	"tinymce/dom/EventUtils",
       
    34 	"tinymce/dom/Sizzle",
       
    35 	"tinymce/util/Tools",
       
    36 	"tinymce/Env"
       
    37 ], function(EventUtils, Sizzle, Tools, Env) {
       
    38 	var doc = document, push = Array.prototype.push, slice = Array.prototype.slice;
       
    39 	var rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;
       
    40 	var Event = EventUtils.Event, undef;
       
    41 
       
    42 	function isDefined(obj) {
       
    43 		return typeof obj !== 'undefined';
       
    44 	}
       
    45 
       
    46 	function isString(obj) {
       
    47 		return typeof obj === 'string';
       
    48 	}
       
    49 
       
    50 	function isWindow(obj) {
       
    51 		return obj && obj == obj.window;
       
    52 	}
       
    53 
       
    54 	function createFragment(html, fragDoc) {
       
    55 		var frag, node, container;
       
    56 
       
    57 		fragDoc = fragDoc || doc;
       
    58 		container = fragDoc.createElement('div');
       
    59 		frag = fragDoc.createDocumentFragment();
       
    60 		container.innerHTML = html;
       
    61 
       
    62 		while ((node = container.firstChild)) {
       
    63 			frag.appendChild(node);
       
    64 		}
       
    65 
       
    66 		return frag;
       
    67 	}
       
    68 
       
    69 	function domManipulate(targetNodes, sourceItem, callback, reverse) {
       
    70 		var i;
       
    71 
       
    72 		if (isString(sourceItem)) {
       
    73 			sourceItem = createFragment(sourceItem, getElementDocument(targetNodes[0]));
       
    74 		} else if (sourceItem.length && !sourceItem.nodeType) {
       
    75 			sourceItem = DomQuery.makeArray(sourceItem);
       
    76 
       
    77 			if (reverse) {
       
    78 				for (i = sourceItem.length - 1; i >= 0; i--) {
       
    79 					domManipulate(targetNodes, sourceItem[i], callback, reverse);
       
    80 				}
       
    81 			} else {
       
    82 				for (i = 0; i < sourceItem.length; i++) {
       
    83 					domManipulate(targetNodes, sourceItem[i], callback, reverse);
       
    84 				}
       
    85 			}
       
    86 
       
    87 			return targetNodes;
       
    88 		}
       
    89 
       
    90 		if (sourceItem.nodeType) {
       
    91 			i = targetNodes.length;
       
    92 			while (i--) {
       
    93 				callback.call(targetNodes[i], sourceItem);
       
    94 			}
       
    95 		}
       
    96 
       
    97 		return targetNodes;
       
    98 	}
       
    99 
       
   100 	function hasClass(node, className) {
       
   101 		return node && className && (' ' + node.className + ' ').indexOf(' ' + className + ' ') !== -1;
       
   102 	}
       
   103 
       
   104 	function wrap(elements, wrapper, all) {
       
   105 		var lastParent, newWrapper;
       
   106 
       
   107 		wrapper = DomQuery(wrapper)[0];
       
   108 
       
   109 		elements.each(function() {
       
   110 			var self = this;
       
   111 
       
   112 			if (!all || lastParent != self.parentNode) {
       
   113 				lastParent = self.parentNode;
       
   114 				newWrapper = wrapper.cloneNode(false);
       
   115 				self.parentNode.insertBefore(newWrapper, self);
       
   116 				newWrapper.appendChild(self);
       
   117 			} else {
       
   118 				newWrapper.appendChild(self);
       
   119 			}
       
   120 		});
       
   121 
       
   122 		return elements;
       
   123 	}
       
   124 
       
   125 	var numericCssMap = Tools.makeMap('fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom', ' ');
       
   126 	var booleanMap = Tools.makeMap('checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected', ' ');
       
   127 	var propFix = {
       
   128 		'for': 'htmlFor',
       
   129 		'class': 'className',
       
   130 		'readonly': 'readOnly'
       
   131 	};
       
   132 	var cssFix = {
       
   133 		'float': 'cssFloat'
       
   134 	};
       
   135 
       
   136 	var attrHooks = {}, cssHooks = {};
       
   137 
       
   138 	function DomQuery(selector, context) {
       
   139 		/*eslint new-cap:0 */
       
   140 		return new DomQuery.fn.init(selector, context);
       
   141 	}
       
   142 
       
   143 	function inArray(item, array) {
       
   144 		var i;
       
   145 
       
   146 		if (array.indexOf) {
       
   147 			return array.indexOf(item);
       
   148 		}
       
   149 
       
   150 		i = array.length;
       
   151 		while (i--) {
       
   152 			if (array[i] === item) {
       
   153 				return i;
       
   154 			}
       
   155 		}
       
   156 
       
   157 		return -1;
       
   158 	}
       
   159 
       
   160 	var whiteSpaceRegExp = /^\s*|\s*$/g;
       
   161 
       
   162 	function trim(str) {
       
   163 		return (str === null || str === undef) ? '' : ("" + str).replace(whiteSpaceRegExp, '');
       
   164 	}
       
   165 
       
   166 	function each(obj, callback) {
       
   167 		var length, key, i, undef, value;
       
   168 
       
   169 		if (obj) {
       
   170 			length = obj.length;
       
   171 
       
   172 			if (length === undef) {
       
   173 				// Loop object items
       
   174 				for (key in obj) {
       
   175 					if (obj.hasOwnProperty(key)) {
       
   176 						value = obj[key];
       
   177 						if (callback.call(value, key, value) === false) {
       
   178 							break;
       
   179 						}
       
   180 					}
       
   181 				}
       
   182 			} else {
       
   183 				// Loop array items
       
   184 				for (i = 0; i < length; i++) {
       
   185 					value = obj[i];
       
   186 					if (callback.call(value, i, value) === false) {
       
   187 						break;
       
   188 					}
       
   189 				}
       
   190 			}
       
   191 		}
       
   192 
       
   193 		return obj;
       
   194 	}
       
   195 
       
   196 	function grep(array, callback) {
       
   197 		var out = [];
       
   198 
       
   199 		each(array, function(i, item) {
       
   200 			if (callback(item, i)) {
       
   201 				out.push(item);
       
   202 			}
       
   203 		});
       
   204 
       
   205 		return out;
       
   206 	}
       
   207 
       
   208 	function getElementDocument(element) {
       
   209 		if (!element) {
       
   210 			return doc;
       
   211 		}
       
   212 
       
   213 		if (element.nodeType == 9) {
       
   214 			return element;
       
   215 		}
       
   216 
       
   217 		return element.ownerDocument;
       
   218 	}
       
   219 
       
   220 	DomQuery.fn = DomQuery.prototype = {
       
   221 		constructor: DomQuery,
       
   222 
       
   223 		/**
       
   224 		 * Selector for the current set.
       
   225 		 *
       
   226 		 * @property selector
       
   227 		 * @type String
       
   228 		 */
       
   229 		selector: "",
       
   230 
       
   231 		/**
       
   232 		 * Context used to create the set.
       
   233 		 *
       
   234 		 * @property context
       
   235 		 * @type Element
       
   236 		 */
       
   237 		context: null,
       
   238 
       
   239 		/**
       
   240 		 * Number of items in the current set.
       
   241 		 *
       
   242 		 * @property length
       
   243 		 * @type Number
       
   244 		 */
       
   245 		length: 0,
       
   246 
       
   247 		/**
       
   248 		 * Constructs a new DomQuery instance with the specified selector or context.
       
   249 		 *
       
   250 		 * @constructor
       
   251 		 * @method init
       
   252 		 * @param {String/Array/DomQuery} selector Optional CSS selector/Array or array like object or HTML string.
       
   253 		 * @param {Document/Element} context Optional context to search in.
       
   254 		 */
       
   255 		init: function(selector, context) {
       
   256 			var self = this, match, node;
       
   257 
       
   258 			if (!selector) {
       
   259 				return self;
       
   260 			}
       
   261 
       
   262 			if (selector.nodeType) {
       
   263 				self.context = self[0] = selector;
       
   264 				self.length = 1;
       
   265 
       
   266 				return self;
       
   267 			}
       
   268 
       
   269 			if (context && context.nodeType) {
       
   270 				self.context = context;
       
   271 			} else {
       
   272 				if (context) {
       
   273 					return DomQuery(selector).attr(context);
       
   274 				} else {
       
   275 					self.context = context = document;
       
   276 				}
       
   277 			}
       
   278 
       
   279 			if (isString(selector)) {
       
   280 				self.selector = selector;
       
   281 
       
   282 				if (selector.charAt(0) === "<" && selector.charAt(selector.length - 1) === ">" && selector.length >= 3) {
       
   283 					match = [null, selector, null];
       
   284 				} else {
       
   285 					match = rquickExpr.exec(selector);
       
   286 				}
       
   287 
       
   288 				if (match) {
       
   289 					if (match[1]) {
       
   290 						node = createFragment(selector, getElementDocument(context)).firstChild;
       
   291 
       
   292 						while (node) {
       
   293 							push.call(self, node);
       
   294 							node = node.nextSibling;
       
   295 						}
       
   296 					} else {
       
   297 						node = getElementDocument(context).getElementById(match[2]);
       
   298 
       
   299 						if (!node) {
       
   300 							return self;
       
   301 						}
       
   302 
       
   303 						if (node.id !== match[2]) {
       
   304 							return self.find(selector);
       
   305 						}
       
   306 
       
   307 						self.length = 1;
       
   308 						self[0] = node;
       
   309 					}
       
   310 				} else {
       
   311 					return DomQuery(context).find(selector);
       
   312 				}
       
   313 			} else {
       
   314 				this.add(selector, false);
       
   315 			}
       
   316 
       
   317 			return self;
       
   318 		},
       
   319 
       
   320 		/**
       
   321 		 * Converts the current set to an array.
       
   322 		 *
       
   323 		 * @method toArray
       
   324 		 * @param {Array} Array of all nodes in set.
       
   325 		 */
       
   326 		toArray: function() {
       
   327 			return Tools.toArray(this);
       
   328 		},
       
   329 
       
   330 		/**
       
   331 		 * Adds new nodes to the set.
       
   332 		 *
       
   333 		 * @method add
       
   334 		 * @param {Array/tinymce.dom.DomQuery} items Array of all nodes to add to set.
       
   335 		 * @return {tinymce.dom.DomQuery} New instance with nodes added.
       
   336 		 */
       
   337 		add: function(items, sort) {
       
   338 			var self = this, nodes, i;
       
   339 
       
   340 			if (isString(items)) {
       
   341 				return self.add(DomQuery(items));
       
   342 			}
       
   343 
       
   344 			if (sort !== false) {
       
   345 				nodes = DomQuery.unique(self.toArray().concat(DomQuery.makeArray(items)));
       
   346 				self.length = nodes.length;
       
   347 				for (i = 0; i < nodes.length; i++) {
       
   348 					self[i] = nodes[i];
       
   349 				}
       
   350 			} else {
       
   351 				push.apply(self, DomQuery.makeArray(items));
       
   352 			}
       
   353 
       
   354 			return self;
       
   355 		},
       
   356 
       
   357 		/**
       
   358 		 * Sets/gets attributes on the elements in the current set.
       
   359 		 *
       
   360 		 * @method attr
       
   361 		 * @param {String/Object} name Name of attribute to get or an object with attributes to set.
       
   362 		 * @param {String} value Optional value to set.
       
   363 		 * @return {tinymce.dom.DomQuery/String} Current set or the specified attribute when only the name is specified.
       
   364 		 */
       
   365 		attr: function(name, value) {
       
   366 			var self = this, hook;
       
   367 
       
   368 			if (typeof name === "object") {
       
   369 				each(name, function(name, value) {
       
   370 					self.attr(name, value);
       
   371 				});
       
   372 			} else if (isDefined(value)) {
       
   373 				this.each(function() {
       
   374 					var hook;
       
   375 
       
   376 					if (this.nodeType === 1) {
       
   377 						hook = attrHooks[name];
       
   378 						if (hook && hook.set) {
       
   379 							hook.set(this, value);
       
   380 							return;
       
   381 						}
       
   382 
       
   383 						if (value === null) {
       
   384 							this.removeAttribute(name, 2);
       
   385 						} else {
       
   386 							this.setAttribute(name, value, 2);
       
   387 						}
       
   388 					}
       
   389 				});
       
   390 			} else {
       
   391 				if (self[0] && self[0].nodeType === 1) {
       
   392 					hook = attrHooks[name];
       
   393 					if (hook && hook.get) {
       
   394 						return hook.get(self[0], name);
       
   395 					}
       
   396 
       
   397 					if (booleanMap[name]) {
       
   398 						return self.prop(name) ? name : undef;
       
   399 					}
       
   400 
       
   401 					value = self[0].getAttribute(name, 2);
       
   402 
       
   403 					if (value === null) {
       
   404 						value = undef;
       
   405 					}
       
   406 				}
       
   407 
       
   408 				return value;
       
   409 			}
       
   410 
       
   411 			return self;
       
   412 		},
       
   413 
       
   414 		/**
       
   415 		 * Removes attributse on the elements in the current set.
       
   416 		 *
       
   417 		 * @method removeAttr
       
   418 		 * @param {String/Object} name Name of attribute to remove.
       
   419 		 * @return {tinymce.dom.DomQuery/String} Current set.
       
   420 		 */
       
   421 		removeAttr: function(name) {
       
   422 			return this.attr(name, null);
       
   423 		},
       
   424 
       
   425 		/**
       
   426 		 * Sets/gets properties on the elements in the current set.
       
   427 		 *
       
   428 		 * @method attr
       
   429 		 * @param {String/Object} name Name of property to get or an object with properties to set.
       
   430 		 * @param {String} value Optional value to set.
       
   431 		 * @return {tinymce.dom.DomQuery/String} Current set or the specified property when only the name is specified.
       
   432 		 */
       
   433 		prop: function(name, value) {
       
   434 			var self = this;
       
   435 
       
   436 			name = propFix[name] || name;
       
   437 
       
   438 			if (typeof name === "object") {
       
   439 				each(name, function(name, value) {
       
   440 					self.prop(name, value);
       
   441 				});
       
   442 			} else if (isDefined(value)) {
       
   443 				this.each(function() {
       
   444 					if (this.nodeType == 1) {
       
   445 						this[name] = value;
       
   446 					}
       
   447 				});
       
   448 			} else {
       
   449 				if (self[0] && self[0].nodeType && name in self[0]) {
       
   450 					return self[0][name];
       
   451 				}
       
   452 
       
   453 				return value;
       
   454 			}
       
   455 
       
   456 			return self;
       
   457 		},
       
   458 
       
   459 		/**
       
   460 		 * Sets/gets styles on the elements in the current set.
       
   461 		 *
       
   462 		 * @method css
       
   463 		 * @param {String/Object} name Name of style to get or an object with styles to set.
       
   464 		 * @param {String} value Optional value to set.
       
   465 		 * @return {tinymce.dom.DomQuery/String} Current set or the specified style when only the name is specified.
       
   466 		 */
       
   467 		css: function(name, value) {
       
   468 			var self = this, elm, hook;
       
   469 
       
   470 			function camel(name) {
       
   471 				return name.replace(/-(\D)/g, function(a, b) {
       
   472 					return b.toUpperCase();
       
   473 				});
       
   474 			}
       
   475 
       
   476 			function dashed(name) {
       
   477 				return name.replace(/[A-Z]/g, function(a) {
       
   478 					return '-' + a;
       
   479 				});
       
   480 			}
       
   481 
       
   482 			if (typeof name === "object") {
       
   483 				each(name, function(name, value) {
       
   484 					self.css(name, value);
       
   485 				});
       
   486 			} else {
       
   487 				if (isDefined(value)) {
       
   488 					name = camel(name);
       
   489 
       
   490 					// Default px suffix on these
       
   491 					if (typeof value === 'number' && !numericCssMap[name]) {
       
   492 						value += 'px';
       
   493 					}
       
   494 
       
   495 					self.each(function() {
       
   496 						var style = this.style;
       
   497 
       
   498 						hook = cssHooks[name];
       
   499 						if (hook && hook.set) {
       
   500 							hook.set(this, value);
       
   501 							return;
       
   502 						}
       
   503 
       
   504 						try {
       
   505 							this.style[cssFix[name] || name] = value;
       
   506 						} catch (ex) {
       
   507 							// Ignore
       
   508 						}
       
   509 
       
   510 						if (value === null || value === '') {
       
   511 							if (style.removeProperty) {
       
   512 								style.removeProperty(dashed(name));
       
   513 							} else {
       
   514 								style.removeAttribute(name);
       
   515 							}
       
   516 						}
       
   517 					});
       
   518 				} else {
       
   519 					elm = self[0];
       
   520 
       
   521 					hook = cssHooks[name];
       
   522 					if (hook && hook.get) {
       
   523 						return hook.get(elm);
       
   524 					}
       
   525 
       
   526 					if (elm.ownerDocument.defaultView) {
       
   527 						try {
       
   528 							return elm.ownerDocument.defaultView.getComputedStyle(elm, null).getPropertyValue(dashed(name));
       
   529 						} catch (ex) {
       
   530 							return undef;
       
   531 						}
       
   532 					} else if (elm.currentStyle) {
       
   533 						return elm.currentStyle[camel(name)];
       
   534 					}
       
   535 				}
       
   536 			}
       
   537 
       
   538 			return self;
       
   539 		},
       
   540 
       
   541 		/**
       
   542 		 * Removes all nodes in set from the document.
       
   543 		 *
       
   544 		 * @method remove
       
   545 		 * @return {tinymce.dom.DomQuery} Current set with the removed nodes.
       
   546 		 */
       
   547 		remove: function() {
       
   548 			var self = this, node, i = this.length;
       
   549 
       
   550 			while (i--) {
       
   551 				node = self[i];
       
   552 				Event.clean(node);
       
   553 
       
   554 				if (node.parentNode) {
       
   555 					node.parentNode.removeChild(node);
       
   556 				}
       
   557 			}
       
   558 
       
   559 			return this;
       
   560 		},
       
   561 
       
   562 		/**
       
   563 		 * Empties all elements in set.
       
   564 		 *
       
   565 		 * @method empty
       
   566 		 * @return {tinymce.dom.DomQuery} Current set with the empty nodes.
       
   567 		 */
       
   568 		empty: function() {
       
   569 			var self = this, node, i = this.length;
       
   570 
       
   571 			while (i--) {
       
   572 				node = self[i];
       
   573 				while (node.firstChild) {
       
   574 					node.removeChild(node.firstChild);
       
   575 				}
       
   576 			}
       
   577 
       
   578 			return this;
       
   579 		},
       
   580 
       
   581 		/**
       
   582 		 * Sets or gets the HTML of the current set or first set node.
       
   583 		 *
       
   584 		 * @method html
       
   585 		 * @param {String} value Optional innerHTML value to set on each element.
       
   586 		 * @return {tinymce.dom.DomQuery/String} Current set or the innerHTML of the first element.
       
   587 		 */
       
   588 		html: function(value) {
       
   589 			var self = this, i;
       
   590 
       
   591 			if (isDefined(value)) {
       
   592 				i = self.length;
       
   593 
       
   594 				try {
       
   595 					while (i--) {
       
   596 						self[i].innerHTML = value;
       
   597 					}
       
   598 				} catch (ex) {
       
   599 					// Workaround for "Unknown runtime error" when DIV is added to P on IE
       
   600 					DomQuery(self[i]).empty().append(value);
       
   601 				}
       
   602 
       
   603 				return self;
       
   604 			}
       
   605 
       
   606 			return self[0] ? self[0].innerHTML : '';
       
   607 		},
       
   608 
       
   609 		/**
       
   610 		 * Sets or gets the text of the current set or first set node.
       
   611 		 *
       
   612 		 * @method text
       
   613 		 * @param {String} value Optional innerText value to set on each element.
       
   614 		 * @return {tinymce.dom.DomQuery/String} Current set or the innerText of the first element.
       
   615 		 */
       
   616 		text: function(value) {
       
   617 			var self = this, i;
       
   618 
       
   619 			if (isDefined(value)) {
       
   620 				i = self.length;
       
   621 				while (i--) {
       
   622 					if ("innerText" in self[i]) {
       
   623 						self[i].innerText = value;
       
   624 					} else {
       
   625 						self[0].textContent = value;
       
   626 					}
       
   627 				}
       
   628 
       
   629 				return self;
       
   630 			}
       
   631 
       
   632 			return self[0] ? (self[0].innerText || self[0].textContent) : '';
       
   633 		},
       
   634 
       
   635 		/**
       
   636 		 * Appends the specified node/html or node set to the current set nodes.
       
   637 		 *
       
   638 		 * @method append
       
   639 		 * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to append to each element in set.
       
   640 		 * @return {tinymce.dom.DomQuery} Current set.
       
   641 		 */
       
   642 		append: function() {
       
   643 			return domManipulate(this, arguments, function(node) {
       
   644 				if (this.nodeType === 1) {
       
   645 					this.appendChild(node);
       
   646 				}
       
   647 			});
       
   648 		},
       
   649 
       
   650 		/**
       
   651 		 * Prepends the specified node/html or node set to the current set nodes.
       
   652 		 *
       
   653 		 * @method prepend
       
   654 		 * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to prepend to each element in set.
       
   655 		 * @return {tinymce.dom.DomQuery} Current set.
       
   656 		 */
       
   657 		prepend: function() {
       
   658 			return domManipulate(this, arguments, function(node) {
       
   659 				if (this.nodeType === 1) {
       
   660 					this.insertBefore(node, this.firstChild);
       
   661 				}
       
   662 			}, true);
       
   663 		},
       
   664 
       
   665 		/**
       
   666 		 * Adds the specified elements before current set nodes.
       
   667 		 *
       
   668 		 * @method before
       
   669 		 * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to add before to each element in set.
       
   670 		 * @return {tinymce.dom.DomQuery} Current set.
       
   671 		 */
       
   672 		before: function() {
       
   673 			var self = this;
       
   674 
       
   675 			if (self[0] && self[0].parentNode) {
       
   676 				return domManipulate(self, arguments, function(node) {
       
   677 					this.parentNode.insertBefore(node, this);
       
   678 				});
       
   679 			}
       
   680 
       
   681 			return self;
       
   682 		},
       
   683 
       
   684 		/**
       
   685 		 * Adds the specified elements after current set nodes.
       
   686 		 *
       
   687 		 * @method after
       
   688 		 * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to add after to each element in set.
       
   689 		 * @return {tinymce.dom.DomQuery} Current set.
       
   690 		 */
       
   691 		after: function() {
       
   692 			var self = this;
       
   693 
       
   694 			if (self[0] && self[0].parentNode) {
       
   695 				return domManipulate(self, arguments, function(node) {
       
   696 					this.parentNode.insertBefore(node, this.nextSibling);
       
   697 				}, true);
       
   698 			}
       
   699 
       
   700 			return self;
       
   701 		},
       
   702 
       
   703 		/**
       
   704 		 * Appends the specified set nodes to the specified selector/instance.
       
   705 		 *
       
   706 		 * @method appendTo
       
   707 		 * @param {String/Element/Array/tinymce.dom.DomQuery} val Item to append the current set to.
       
   708 		 * @return {tinymce.dom.DomQuery} Current set with the appended nodes.
       
   709 		 */
       
   710 		appendTo: function(val) {
       
   711 			DomQuery(val).append(this);
       
   712 
       
   713 			return this;
       
   714 		},
       
   715 
       
   716 		/**
       
   717 		 * Prepends the specified set nodes to the specified selector/instance.
       
   718 		 *
       
   719 		 * @method prependTo
       
   720 		 * @param {String/Element/Array/tinymce.dom.DomQuery} val Item to prepend the current set to.
       
   721 		 * @return {tinymce.dom.DomQuery} Current set with the prepended nodes.
       
   722 		 */
       
   723 		prependTo: function(val) {
       
   724 			DomQuery(val).prepend(this);
       
   725 
       
   726 			return this;
       
   727 		},
       
   728 
       
   729 		/**
       
   730 		 * Replaces the nodes in set with the specified content.
       
   731 		 *
       
   732 		 * @method replaceWith
       
   733 		 * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to replace nodes with.
       
   734 		 * @return {tinymce.dom.DomQuery} Set with replaced nodes.
       
   735 		 */
       
   736 		replaceWith: function(content) {
       
   737 			return this.before(content).remove();
       
   738 		},
       
   739 
       
   740 		/**
       
   741 		 * Wraps all elements in set with the specified wrapper.
       
   742 		 *
       
   743 		 * @method wrap
       
   744 		 * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
       
   745 		 * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
       
   746 		 */
       
   747 		wrap: function(wrapper) {
       
   748 			return wrap(this, wrapper);
       
   749 		},
       
   750 
       
   751 		/**
       
   752 		 * Wraps all nodes in set with the specified wrapper. If the nodes are siblings all of them
       
   753 		 * will be wrapped in the same wrapper.
       
   754 		 *
       
   755 		 * @method wrapAll
       
   756 		 * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
       
   757 		 * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
       
   758 		 */
       
   759 		wrapAll: function(wrapper) {
       
   760 			return wrap(this, wrapper, true);
       
   761 		},
       
   762 
       
   763 		/**
       
   764 		 * Wraps all elements inner contents in set with the specified wrapper.
       
   765 		 *
       
   766 		 * @method wrapInner
       
   767 		 * @param {String/Element/Array/tinymce.dom.DomQuery} content Content to wrap nodes with.
       
   768 		 * @return {tinymce.dom.DomQuery} Set with wrapped nodes.
       
   769 		 */
       
   770 		wrapInner: function(wrapper) {
       
   771 			this.each(function() {
       
   772 				DomQuery(this).contents().wrapAll(wrapper);
       
   773 			});
       
   774 
       
   775 			return this;
       
   776 		},
       
   777 
       
   778 		/**
       
   779 		 * Unwraps all elements by removing the parent element of each item in set.
       
   780 		 *
       
   781 		 * @method unwrap
       
   782 		 * @return {tinymce.dom.DomQuery} Set with unwrapped nodes.
       
   783 		 */
       
   784 		unwrap: function() {
       
   785 			return this.parent().each(function() {
       
   786 				DomQuery(this).replaceWith(this.childNodes);
       
   787 			});
       
   788 		},
       
   789 
       
   790 		/**
       
   791 		 * Clones all nodes in set.
       
   792 		 *
       
   793 		 * @method clone
       
   794 		 * @return {tinymce.dom.DomQuery} Set with cloned nodes.
       
   795 		 */
       
   796 		clone: function() {
       
   797 			var result = [];
       
   798 
       
   799 			this.each(function() {
       
   800 				result.push(this.cloneNode(true));
       
   801 			});
       
   802 
       
   803 			return DomQuery(result);
       
   804 		},
       
   805 
       
   806 		/**
       
   807 		 * Adds the specified class name to the current set elements.
       
   808 		 *
       
   809 		 * @method addClass
       
   810 		 * @param {String} className Class name to add.
       
   811 		 * @return {tinymce.dom.DomQuery} Current set.
       
   812 		 */
       
   813 		addClass: function(className) {
       
   814 			return this.toggleClass(className, true);
       
   815 		},
       
   816 
       
   817 		/**
       
   818 		 * Removes the specified class name to the current set elements.
       
   819 		 *
       
   820 		 * @method removeClass
       
   821 		 * @param {String} className Class name to remove.
       
   822 		 * @return {tinymce.dom.DomQuery} Current set.
       
   823 		 */
       
   824 		removeClass: function(className) {
       
   825 			return this.toggleClass(className, false);
       
   826 		},
       
   827 
       
   828 		/**
       
   829 		 * Toggles the specified class name on the current set elements.
       
   830 		 *
       
   831 		 * @method toggleClass
       
   832 		 * @param {String} className Class name to add/remove.
       
   833 		 * @param {Boolean} state Optional state to toggle on/off.
       
   834 		 * @return {tinymce.dom.DomQuery} Current set.
       
   835 		 */
       
   836 		toggleClass: function(className, state) {
       
   837 			var self = this;
       
   838 
       
   839 			// Functions are not supported
       
   840 			if (typeof className != 'string') {
       
   841 				return self;
       
   842 			}
       
   843 
       
   844 			if (className.indexOf(' ') !== -1) {
       
   845 				each(className.split(' '), function() {
       
   846 					self.toggleClass(this, state);
       
   847 				});
       
   848 			} else {
       
   849 				self.each(function(index, node) {
       
   850 					var existingClassName, classState;
       
   851 
       
   852 					classState = hasClass(node, className);
       
   853 					if (classState !== state) {
       
   854 						existingClassName = node.className;
       
   855 
       
   856 						if (classState) {
       
   857 							node.className = trim((" " + existingClassName + " ").replace(' ' + className + ' ', ' '));
       
   858 						} else {
       
   859 							node.className += existingClassName ? ' ' + className : className;
       
   860 						}
       
   861 					}
       
   862 				});
       
   863 			}
       
   864 
       
   865 			return self;
       
   866 		},
       
   867 
       
   868 		/**
       
   869 		 * Returns true/false if the first item in set has the specified class.
       
   870 		 *
       
   871 		 * @method hasClass
       
   872 		 * @param {String} className Class name to check for.
       
   873 		 * @return {Boolean} True/false if the set has the specified class.
       
   874 		 */
       
   875 		hasClass: function(className) {
       
   876 			return hasClass(this[0], className);
       
   877 		},
       
   878 
       
   879 		/**
       
   880 		 * Executes the callback function for each item DomQuery collection. If you return false in the
       
   881 		 * callback it will break the loop.
       
   882 		 *
       
   883 		 * @method each
       
   884 		 * @param {function} callback Callback function to execute for each item.
       
   885 		 * @return {tinymce.dom.DomQuery} Current set.
       
   886 		 */
       
   887 		each: function(callback) {
       
   888 			return each(this, callback);
       
   889 		},
       
   890 
       
   891 		/**
       
   892 		 * Binds an event with callback function to the elements in set.
       
   893 		 *
       
   894 		 * @method on
       
   895 		 * @param {String} name Name of the event to bind.
       
   896 		 * @param {function} callback Callback function to execute when the event occurs.
       
   897 		 * @return {tinymce.dom.DomQuery} Current set.
       
   898 		 */
       
   899 		on: function(name, callback) {
       
   900 			return this.each(function() {
       
   901 				Event.bind(this, name, callback);
       
   902 			});
       
   903 		},
       
   904 
       
   905 		/**
       
   906 		 * Unbinds an event with callback function to the elements in set.
       
   907 		 *
       
   908 		 * @method off
       
   909 		 * @param {String} name Optional name of the event to bind.
       
   910 		 * @param {function} callback Optional callback function to execute when the event occurs.
       
   911 		 * @return {tinymce.dom.DomQuery} Current set.
       
   912 		 */
       
   913 		off: function(name, callback) {
       
   914 			return this.each(function() {
       
   915 				Event.unbind(this, name, callback);
       
   916 			});
       
   917 		},
       
   918 
       
   919 		/**
       
   920 		 * Triggers the specified event by name or event object.
       
   921 		 *
       
   922 		 * @method trigger
       
   923 		 * @param {String/Object} name Name of the event to trigger or event object.
       
   924 		 * @return {tinymce.dom.DomQuery} Current set.
       
   925 		 */
       
   926 		trigger: function(name) {
       
   927 			return this.each(function() {
       
   928 				if (typeof name == 'object') {
       
   929 					Event.fire(this, name.type, name);
       
   930 				} else {
       
   931 					Event.fire(this, name);
       
   932 				}
       
   933 			});
       
   934 		},
       
   935 
       
   936 		/**
       
   937 		 * Shows all elements in set.
       
   938 		 *
       
   939 		 * @method show
       
   940 		 * @return {tinymce.dom.DomQuery} Current set.
       
   941 		 */
       
   942 		show: function() {
       
   943 			return this.css('display', '');
       
   944 		},
       
   945 
       
   946 		/**
       
   947 		 * Hides all elements in set.
       
   948 		 *
       
   949 		 * @method hide
       
   950 		 * @return {tinymce.dom.DomQuery} Current set.
       
   951 		 */
       
   952 		hide: function() {
       
   953 			return this.css('display', 'none');
       
   954 		},
       
   955 
       
   956 		/**
       
   957 		 * Slices the current set.
       
   958 		 *
       
   959 		 * @method slice
       
   960 		 * @param {Number} start Start index to slice at.
       
   961 		 * @param {Number} end Optional ened index to end slice at.
       
   962 		 * @return {tinymce.dom.DomQuery} Sliced set.
       
   963 		 */
       
   964 		slice: function() {
       
   965 			return new DomQuery(slice.apply(this, arguments));
       
   966 		},
       
   967 
       
   968 		/**
       
   969 		 * Makes the set equal to the specified index.
       
   970 		 *
       
   971 		 * @method eq
       
   972 		 * @param {Number} index Index to set it equal to.
       
   973 		 * @return {tinymce.dom.DomQuery} Single item set.
       
   974 		 */
       
   975 		eq: function(index) {
       
   976 			return index === -1 ? this.slice(index) : this.slice(index, +index + 1);
       
   977 		},
       
   978 
       
   979 		/**
       
   980 		 * Makes the set equal to first element in set.
       
   981 		 *
       
   982 		 * @method first
       
   983 		 * @return {tinymce.dom.DomQuery} Single item set.
       
   984 		 */
       
   985 		first: function() {
       
   986 			return this.eq(0);
       
   987 		},
       
   988 
       
   989 		/**
       
   990 		 * Makes the set equal to last element in set.
       
   991 		 *
       
   992 		 * @method last
       
   993 		 * @return {tinymce.dom.DomQuery} Single item set.
       
   994 		 */
       
   995 		last: function() {
       
   996 			return this.eq(-1);
       
   997 		},
       
   998 
       
   999 		/**
       
  1000 		 * Finds elements by the specified selector for each element in set.
       
  1001 		 *
       
  1002 		 * @method find
       
  1003 		 * @param {String} selector Selector to find elements by.
       
  1004 		 * @return {tinymce.dom.DomQuery} Set with matches elements.
       
  1005 		 */
       
  1006 		find: function(selector) {
       
  1007 			var i, l, ret = [];
       
  1008 
       
  1009 			for (i = 0, l = this.length; i < l; i++) {
       
  1010 				DomQuery.find(selector, this[i], ret);
       
  1011 			}
       
  1012 
       
  1013 			return DomQuery(ret);
       
  1014 		},
       
  1015 
       
  1016 		/**
       
  1017 		 * Filters the current set with the specified selector.
       
  1018 		 *
       
  1019 		 * @method filter
       
  1020 		 * @param {String/function} selector Selector to filter elements by.
       
  1021 		 * @return {tinymce.dom.DomQuery} Set with filtered elements.
       
  1022 		 */
       
  1023 		filter: function(selector) {
       
  1024 			if (typeof selector == 'function') {
       
  1025 				return DomQuery(grep(this.toArray(), function(item, i) {
       
  1026 					return selector(i, item);
       
  1027 				}));
       
  1028 			}
       
  1029 
       
  1030 			return DomQuery(DomQuery.filter(selector, this.toArray()));
       
  1031 		},
       
  1032 
       
  1033 		/**
       
  1034 		 * Gets the current node or any partent matching the specified selector.
       
  1035 		 *
       
  1036 		 * @method closest
       
  1037 		 * @param {String/Element/tinymce.dom.DomQuery} selector Selector or element to find.
       
  1038 		 * @return {tinymce.dom.DomQuery} Set with closest elements.
       
  1039 		 */
       
  1040 		closest: function(selector) {
       
  1041 			var result = [];
       
  1042 
       
  1043 			if (selector instanceof DomQuery) {
       
  1044 				selector = selector[0];
       
  1045 			}
       
  1046 
       
  1047 			this.each(function(i, node) {
       
  1048 				while (node) {
       
  1049 					if (typeof selector == 'string' && DomQuery(node).is(selector)) {
       
  1050 						result.push(node);
       
  1051 						break;
       
  1052 					} else if (node == selector) {
       
  1053 						result.push(node);
       
  1054 						break;
       
  1055 					}
       
  1056 
       
  1057 					node = node.parentNode;
       
  1058 				}
       
  1059 			});
       
  1060 
       
  1061 			return DomQuery(result);
       
  1062 		},
       
  1063 
       
  1064 		/**
       
  1065 		 * Returns the offset of the first element in set or sets the top/left css properties of all elements in set.
       
  1066 		 *
       
  1067 		 * @method offset
       
  1068 		 * @param {Object} offset Optional offset object to set on each item.
       
  1069 		 * @return {Object/tinymce.dom.DomQuery} Returns the first element offset or the current set if you specified an offset.
       
  1070 		 */
       
  1071 		offset: function(offset) {
       
  1072 			var elm, doc, docElm;
       
  1073 			var x = 0, y = 0, pos;
       
  1074 
       
  1075 			if (!offset) {
       
  1076 				elm = this[0];
       
  1077 
       
  1078 				if (elm) {
       
  1079 					doc = elm.ownerDocument;
       
  1080 					docElm = doc.documentElement;
       
  1081 
       
  1082 					if (elm.getBoundingClientRect) {
       
  1083 						pos = elm.getBoundingClientRect();
       
  1084 						x = pos.left + (docElm.scrollLeft || doc.body.scrollLeft) - docElm.clientLeft;
       
  1085 						y = pos.top + (docElm.scrollTop || doc.body.scrollTop) - docElm.clientTop;
       
  1086 					}
       
  1087 				}
       
  1088 
       
  1089 				return {
       
  1090 					left: x,
       
  1091 					top: y
       
  1092 				};
       
  1093 			}
       
  1094 
       
  1095 			return this.css(offset);
       
  1096 		},
       
  1097 
       
  1098 		push: push,
       
  1099 		sort: [].sort,
       
  1100 		splice: [].splice
       
  1101 	};
       
  1102 
       
  1103 	// Static members
       
  1104 	Tools.extend(DomQuery, {
       
  1105 		/**
       
  1106 		 * Extends the specified object with one or more objects.
       
  1107 		 *
       
  1108 		 * @static
       
  1109 		 * @method extend
       
  1110 		 * @param {Object} target Target object to extend with new items.
       
  1111 		 * @param {Object..} object Object to extend the target with.
       
  1112 		 * @return {Object} Extended input object.
       
  1113 		 */
       
  1114 		extend: Tools.extend,
       
  1115 
       
  1116 		/**
       
  1117 		 * Creates an array out of an array like object.
       
  1118 		 *
       
  1119 		 * @static
       
  1120 		 * @method makeArray
       
  1121 		 * @param {Object} object Object to convert to array.
       
  1122 		 * @return {Arrau} Array produced from object.
       
  1123 		 */
       
  1124 		makeArray: function(array) {
       
  1125 			if (isWindow(array) || array.nodeType) {
       
  1126 				return [array];
       
  1127 			}
       
  1128 
       
  1129 			return Tools.toArray(array);
       
  1130 		},
       
  1131 
       
  1132 		/**
       
  1133 		 * Returns the index of the specified item inside the array.
       
  1134 		 *
       
  1135 		 * @static
       
  1136 		 * @method inArray
       
  1137 		 * @param {Object} item Item to look for.
       
  1138 		 * @param {Array} array Array to look for item in.
       
  1139 		 * @return {Number} Index of the item or -1.
       
  1140 		 */
       
  1141 		inArray: inArray,
       
  1142 
       
  1143 		/**
       
  1144 		 * Returns true/false if the specified object is an array or not.
       
  1145 		 *
       
  1146 		 * @static
       
  1147 		 * @method isArray
       
  1148 		 * @param {Object} array Object to check if it's an array or not.
       
  1149 		 * @return {Boolean} True/false if the object is an array.
       
  1150 		 */
       
  1151 		isArray: Tools.isArray,
       
  1152 
       
  1153 		/**
       
  1154 		 * Executes the callback function for each item in array/object. If you return false in the
       
  1155 		 * callback it will break the loop.
       
  1156 		 *
       
  1157 		 * @static
       
  1158 		 * @method each
       
  1159 		 * @param {Object} obj Object to iterate.
       
  1160 		 * @param {function} callback Callback function to execute for each item.
       
  1161 		 */
       
  1162 		each: each,
       
  1163 
       
  1164 		/**
       
  1165 		 * Removes whitespace from the beginning and end of a string.
       
  1166 		 *
       
  1167 		 * @static
       
  1168 		 * @method trim
       
  1169 		 * @param {String} str String to remove whitespace from.
       
  1170 		 * @return {String} New string with removed whitespace.
       
  1171 		 */
       
  1172 		trim: trim,
       
  1173 
       
  1174 		/**
       
  1175 		 * Filters out items from the input array by calling the specified function for each item.
       
  1176 		 * If the function returns false the item will be excluded if it returns true it will be included.
       
  1177 		 *
       
  1178 		 * @static
       
  1179 		 * @method grep
       
  1180 		 * @param {Array} array Array of items to loop though.
       
  1181 		 * @param {function} callback Function to call for each item. Include/exclude depends on it's return value.
       
  1182 		 * @return {Array} New array with values imported and filtered based in input.
       
  1183 		 * @example
       
  1184 		 * // Filter out some items, this will return an array with 4 and 5
       
  1185 		 * var items = DomQuery.grep([1, 2, 3, 4, 5], function(v) {return v > 3;});
       
  1186 		 */
       
  1187 		grep: grep,
       
  1188 
       
  1189 		// Sizzle
       
  1190 		find: Sizzle,
       
  1191 		expr: Sizzle.selectors,
       
  1192 		unique: Sizzle.uniqueSort,
       
  1193 		text: Sizzle.getText,
       
  1194 		contains: Sizzle.contains,
       
  1195 		filter: function(expr, elems, not) {
       
  1196 			var i = elems.length;
       
  1197 
       
  1198 			if (not) {
       
  1199 				expr = ":not(" + expr + ")";
       
  1200 			}
       
  1201 
       
  1202 			while (i--) {
       
  1203 				if (elems[i].nodeType != 1) {
       
  1204 					elems.splice(i, 1);
       
  1205 				}
       
  1206 			}
       
  1207 
       
  1208 			if (elems.length === 1) {
       
  1209 				elems = DomQuery.find.matchesSelector(elems[0], expr) ? [elems[0]] : [];
       
  1210 			} else {
       
  1211 				elems = DomQuery.find.matches(expr, elems);
       
  1212 			}
       
  1213 
       
  1214 			return elems;
       
  1215 		}
       
  1216 	});
       
  1217 
       
  1218 	function dir(el, prop, until) {
       
  1219 		var matched = [], cur = el[prop];
       
  1220 
       
  1221 		if (typeof until != 'string' && until instanceof DomQuery) {
       
  1222 			until = until[0];
       
  1223 		}
       
  1224 
       
  1225 		while (cur && cur.nodeType !== 9) {
       
  1226 			if (until !== undefined) {
       
  1227 				if (cur === until) {
       
  1228 					break;
       
  1229 				}
       
  1230 
       
  1231 				if (typeof until == 'string' && DomQuery(cur).is(until)) {
       
  1232 					break;
       
  1233 				}
       
  1234 			}
       
  1235 
       
  1236 			if (cur.nodeType === 1) {
       
  1237 				matched.push(cur);
       
  1238 			}
       
  1239 
       
  1240 			cur = cur[prop];
       
  1241 		}
       
  1242 
       
  1243 		return matched;
       
  1244 	}
       
  1245 
       
  1246 	function sibling(node, siblingName, nodeType, until) {
       
  1247 		var result = [];
       
  1248 
       
  1249 		if (until instanceof DomQuery) {
       
  1250 			until = until[0];
       
  1251 		}
       
  1252 
       
  1253 		for (; node; node = node[siblingName]) {
       
  1254 			if (nodeType && node.nodeType !== nodeType) {
       
  1255 				continue;
       
  1256 			}
       
  1257 
       
  1258 			if (until !== undefined) {
       
  1259 				if (node === until) {
       
  1260 					break;
       
  1261 				}
       
  1262 
       
  1263 				if (typeof until == 'string' && DomQuery(node).is(until)) {
       
  1264 					break;
       
  1265 				}
       
  1266 			}
       
  1267 
       
  1268 			result.push(node);
       
  1269 		}
       
  1270 
       
  1271 		return result;
       
  1272 	}
       
  1273 
       
  1274 	function firstSibling(node, siblingName, nodeType) {
       
  1275 		for (node = node[siblingName]; node; node = node[siblingName]) {
       
  1276 			if (node.nodeType == nodeType) {
       
  1277 				return node;
       
  1278 			}
       
  1279 		}
       
  1280 
       
  1281 		return null;
       
  1282 	}
       
  1283 
       
  1284 	each({
       
  1285 		/**
       
  1286 		 * Returns a new collection with the parent of each item in current collection matching the optional selector.
       
  1287 		 *
       
  1288 		 * @method parent
       
  1289 		 * @param {String} selector Selector to match parents agains.
       
  1290 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
       
  1291 		 */
       
  1292 		parent: function(node) {
       
  1293 			var parent = node.parentNode;
       
  1294 
       
  1295 			return parent && parent.nodeType !== 11 ? parent : null;
       
  1296 		},
       
  1297 
       
  1298 		/**
       
  1299 		 * Returns a new collection with the all the parents of each item in current collection matching the optional selector.
       
  1300 		 *
       
  1301 		 * @method parents
       
  1302 		 * @param {String} selector Selector to match parents agains.
       
  1303 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
       
  1304 		 */
       
  1305 		parents: function(node) {
       
  1306 			return dir(node, "parentNode");
       
  1307 		},
       
  1308 
       
  1309 		/**
       
  1310 		 * Returns a new collection with next sibling of each item in current collection matching the optional selector.
       
  1311 		 *
       
  1312 		 * @method next
       
  1313 		 * @param {String} selector Selector to match the next element against.
       
  1314 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
       
  1315 		 */
       
  1316 		next: function(node) {
       
  1317 			return firstSibling(node, 'nextSibling', 1);
       
  1318 		},
       
  1319 
       
  1320 		/**
       
  1321 		 * Returns a new collection with previous sibling of each item in current collection matching the optional selector.
       
  1322 		 *
       
  1323 		 * @method prev
       
  1324 		 * @param {String} selector Selector to match the previous element against.
       
  1325 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
       
  1326 		 */
       
  1327 		prev: function(node) {
       
  1328 			return firstSibling(node, 'previousSibling', 1);
       
  1329 		},
       
  1330 
       
  1331 		/**
       
  1332 		 * Returns all child elements matching the optional selector.
       
  1333 		 *
       
  1334 		 * @method children
       
  1335 		 * @param {String} selector Selector to match the elements against.
       
  1336 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
       
  1337 		 */
       
  1338 		children: function(node) {
       
  1339 			return sibling(node.firstChild, 'nextSibling', 1);
       
  1340 		},
       
  1341 
       
  1342 		/**
       
  1343 		 * Returns all child nodes matching the optional selector.
       
  1344 		 *
       
  1345 		 * @method contents
       
  1346 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
       
  1347 		 */
       
  1348 		contents: function(node) {
       
  1349 			return Tools.toArray((node.nodeName === "iframe" ? node.contentDocument || node.contentWindow.document : node).childNodes);
       
  1350 		}
       
  1351 	}, function(name, fn) {
       
  1352 		DomQuery.fn[name] = function(selector) {
       
  1353 			var self = this, result = [];
       
  1354 
       
  1355 			self.each(function() {
       
  1356 				var nodes = fn.call(result, this, selector, result);
       
  1357 
       
  1358 				if (nodes) {
       
  1359 					if (DomQuery.isArray(nodes)) {
       
  1360 						result.push.apply(result, nodes);
       
  1361 					} else {
       
  1362 						result.push(nodes);
       
  1363 					}
       
  1364 				}
       
  1365 			});
       
  1366 
       
  1367 			// If traversing on multiple elements we might get the same elements twice
       
  1368 			if (this.length > 1) {
       
  1369 				result = DomQuery.unique(result);
       
  1370 
       
  1371 				if (name.indexOf('parents') === 0) {
       
  1372 					result = result.reverse();
       
  1373 				}
       
  1374 			}
       
  1375 
       
  1376 			result = DomQuery(result);
       
  1377 
       
  1378 			if (selector) {
       
  1379 				return result.filter(selector);
       
  1380 			}
       
  1381 
       
  1382 			return result;
       
  1383 		};
       
  1384 	});
       
  1385 
       
  1386 	each({
       
  1387 		/**
       
  1388 		 * Returns a new collection with the all the parents until the matching selector/element
       
  1389 		 * of each item in current collection matching the optional selector.
       
  1390 		 *
       
  1391 		 * @method parentsUntil
       
  1392 		 * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
       
  1393 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching parents.
       
  1394 		 */
       
  1395 		parentsUntil: function(node, until) {
       
  1396 			return dir(node, "parentNode", until);
       
  1397 		},
       
  1398 
       
  1399 		/**
       
  1400 		 * Returns a new collection with all next siblings of each item in current collection matching the optional selector.
       
  1401 		 *
       
  1402 		 * @method nextUntil
       
  1403 		 * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
       
  1404 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
       
  1405 		 */
       
  1406 		nextUntil: function(node, until) {
       
  1407 			return sibling(node, 'nextSibling', 1, until).slice(1);
       
  1408 		},
       
  1409 
       
  1410 		/**
       
  1411 		 * Returns a new collection with all previous siblings of each item in current collection matching the optional selector.
       
  1412 		 *
       
  1413 		 * @method prevUntil
       
  1414 		 * @param {String/Element/tinymce.dom.DomQuery} until Until the matching selector or element.
       
  1415 		 * @return {tinymce.dom.DomQuery} New DomQuery instance with all matching elements.
       
  1416 		 */
       
  1417 		prevUntil: function(node, until) {
       
  1418 			return sibling(node, 'previousSibling', 1, until).slice(1);
       
  1419 		}
       
  1420 	}, function(name, fn) {
       
  1421 		DomQuery.fn[name] = function(selector, filter) {
       
  1422 			var self = this, result = [];
       
  1423 
       
  1424 			self.each(function() {
       
  1425 				var nodes = fn.call(result, this, selector, result);
       
  1426 
       
  1427 				if (nodes) {
       
  1428 					if (DomQuery.isArray(nodes)) {
       
  1429 						result.push.apply(result, nodes);
       
  1430 					} else {
       
  1431 						result.push(nodes);
       
  1432 					}
       
  1433 				}
       
  1434 			});
       
  1435 
       
  1436 			// If traversing on multiple elements we might get the same elements twice
       
  1437 			if (this.length > 1) {
       
  1438 				result = DomQuery.unique(result);
       
  1439 
       
  1440 				if (name.indexOf('parents') === 0 || name === 'prevUntil') {
       
  1441 					result = result.reverse();
       
  1442 				}
       
  1443 			}
       
  1444 
       
  1445 			result = DomQuery(result);
       
  1446 
       
  1447 			if (filter) {
       
  1448 				return result.filter(filter);
       
  1449 			}
       
  1450 
       
  1451 			return result;
       
  1452 		};
       
  1453 	});
       
  1454 
       
  1455 	/**
       
  1456 	 * Returns true/false if the current set items matches the selector.
       
  1457 	 *
       
  1458 	 * @method is
       
  1459 	 * @param {String} selector Selector to match the elements against.
       
  1460 	 * @return {Boolean} True/false if the current set matches the selector.
       
  1461 	 */
       
  1462 	DomQuery.fn.is = function(selector) {
       
  1463 		return !!selector && this.filter(selector).length > 0;
       
  1464 	};
       
  1465 
       
  1466 	DomQuery.fn.init.prototype = DomQuery.fn;
       
  1467 
       
  1468 	DomQuery.overrideDefaults = function(callback) {
       
  1469 		var defaults;
       
  1470 
       
  1471 		function sub(selector, context) {
       
  1472 			defaults = defaults || callback();
       
  1473 
       
  1474 			if (arguments.length === 0) {
       
  1475 				selector = defaults.element;
       
  1476 			}
       
  1477 
       
  1478 			if (!context) {
       
  1479 				context = defaults.context;
       
  1480 			}
       
  1481 
       
  1482 			return new sub.fn.init(selector, context);
       
  1483 		}
       
  1484 
       
  1485 		DomQuery.extend(sub, this);
       
  1486 
       
  1487 		return sub;
       
  1488 	};
       
  1489 
       
  1490 	function appendHooks(targetHooks, prop, hooks) {
       
  1491 		each(hooks, function(name, func) {
       
  1492 			targetHooks[name] = targetHooks[name] || {};
       
  1493 			targetHooks[name][prop] = func;
       
  1494 		});
       
  1495 	}
       
  1496 
       
  1497 	if (Env.ie && Env.ie < 8) {
       
  1498 		appendHooks(attrHooks, 'get', {
       
  1499 			maxlength: function(elm) {
       
  1500 				var value = elm.maxLength;
       
  1501 
       
  1502 				if (value === 0x7fffffff) {
       
  1503 					return undef;
       
  1504 				}
       
  1505 
       
  1506 				return value;
       
  1507 			},
       
  1508 
       
  1509 			size: function(elm) {
       
  1510 				var value = elm.size;
       
  1511 
       
  1512 				if (value === 20) {
       
  1513 					return undef;
       
  1514 				}
       
  1515 
       
  1516 				return value;
       
  1517 			},
       
  1518 
       
  1519 			'class': function(elm) {
       
  1520 				return elm.className;
       
  1521 			},
       
  1522 
       
  1523 			style: function(elm) {
       
  1524 				var value = elm.style.cssText;
       
  1525 
       
  1526 				if (value.length === 0) {
       
  1527 					return undef;
       
  1528 				}
       
  1529 
       
  1530 				return value;
       
  1531 			}
       
  1532 		});
       
  1533 
       
  1534 		appendHooks(attrHooks, 'set', {
       
  1535 			'class': function(elm, value) {
       
  1536 				elm.className = value;
       
  1537 			},
       
  1538 
       
  1539 			style: function(elm, value) {
       
  1540 				elm.style.cssText = value;
       
  1541 			}
       
  1542 		});
       
  1543 	}
       
  1544 
       
  1545 	if (Env.ie && Env.ie < 9) {
       
  1546 		/*jshint sub:true */
       
  1547 		/*eslint dot-notation: 0*/
       
  1548 		cssFix['float'] = 'styleFloat';
       
  1549 
       
  1550 		appendHooks(cssHooks, 'set', {
       
  1551 			opacity: function(elm, value) {
       
  1552 				var style = elm.style;
       
  1553 
       
  1554 				if (value === null || value === '') {
       
  1555 					style.removeAttribute('filter');
       
  1556 				} else {
       
  1557 					style.zoom = 1;
       
  1558 					style.filter = 'alpha(opacity=' + (value * 100) + ')';
       
  1559 				}
       
  1560 			}
       
  1561 		});
       
  1562 	}
       
  1563 
       
  1564 	DomQuery.attrHooks = attrHooks;
       
  1565 	DomQuery.cssHooks = cssHooks;
       
  1566 
       
  1567 	return DomQuery;
       
  1568 });