diff -r 000000000000 -r 40c8f766c9b8 src/cm/media/js/lib/yui/yui3.0.0/build/dom/dom-base.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm/media/js/lib/yui/yui3.0.0/build/dom/dom-base.js Mon Nov 23 15:14:29 2009 +0100 @@ -0,0 +1,737 @@ +/* +Copyright (c) 2009, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 3.0.0 +build: 1549 +*/ +YUI.add('dom-base', function(Y) { + +(function(Y) { +/** + * The DOM utility provides a cross-browser abtraction layer + * normalizing DOM tasks, and adds extra helper functionality + * for other common tasks. + * @module dom + * @submodule dom-base + * + */ + +/** + * Provides DOM helper methods. + * @class DOM + * + */ +var NODE_TYPE = 'nodeType', + OWNER_DOCUMENT = 'ownerDocument', + DEFAULT_VIEW = 'defaultView', + PARENT_WINDOW = 'parentWindow', + TAG_NAME = 'tagName', + PARENT_NODE = 'parentNode', + FIRST_CHILD = 'firstChild', + PREVIOUS_SIBLING = 'previousSibling', + NEXT_SIBLING = 'nextSibling', + CONTAINS = 'contains', + COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition', + + documentElement = document.documentElement, + + re_tag = /<([a-z]+)/i; + +Y.DOM = { + /** + * Returns the HTMLElement with the given ID (Wrapper for document.getElementById). + * @method byId + * @param {String} id the id attribute + * @param {Object} doc optional The document to search. Defaults to current document + * @return {HTMLElement | null} The HTMLElement with the id, or null if none found. + */ + byId: function(id, doc) { + doc = doc || Y.config.doc; + // TODO: IE Name + return doc.getElementById(id); + }, + + // @deprecated + children: function(node, tag) { + var ret = []; + if (node) { + tag = tag || '*'; + ret = Y.Selector.query('> ' + tag, node); + } + return ret; + }, + + // @deprecated + firstByTag: function(tag, root) { + var ret; + root = root || Y.config.doc; + + if (tag && root.getElementsByTagName) { + ret = root.getElementsByTagName(tag)[0]; + } + + return ret || null; + }, + + /** + * Returns the text content of the HTMLElement. + * @method getText + * @param {HTMLElement} element The html element. + * @return {String} The text content of the element (includes text of any descending elements). + */ + getText: (documentElement.textContent !== undefined) ? + function(element) { + var ret = ''; + if (element) { + ret = element.textContent; + } + return ret || ''; + } : function(element) { + var ret = ''; + if (element) { + ret = element.innerText; + } + return ret || ''; + }, + + /** + * Sets the text content of the HTMLElement. + * @method setText + * @param {HTMLElement} element The html element. + * @param {String} content The content to add. + */ + setText: (documentElement.textContent !== undefined) ? + function(element, content) { + if (element) { + element.textContent = content; + } + } : function(element, content) { + if (element) { + element.innerText = content; + } + }, + + /* + * Finds the previous sibling of the element. + * @method previous + * @deprecated Use elementByAxis + * @param {HTMLElement} element The html element. + * @param {Function} fn optional An optional boolean test to apply. + * The optional function is passed the current DOM node being tested as its only argument. + * If no function is given, the first sibling is returned. + * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes. + * @return {HTMLElement | null} The matching DOM node or null if none found. + */ + previous: function(element, fn, all) { + return Y.DOM.elementByAxis(element, PREVIOUS_SIBLING, fn, all); + }, + + /* + * Finds the next sibling of the element. + * @method next + * @deprecated Use elementByAxis + * @param {HTMLElement} element The html element. + * @param {Function} fn optional An optional boolean test to apply. + * The optional function is passed the current DOM node being tested as its only argument. + * If no function is given, the first sibling is returned. + * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes. + * @return {HTMLElement | null} The matching DOM node or null if none found. + */ + next: function(element, fn, all) { + return Y.DOM.elementByAxis(element, NEXT_SIBLING, fn, all); + }, + + /* + * Finds the ancestor of the element. + * @method ancestor + * @deprecated Use elementByAxis + * @param {HTMLElement} element The html element. + * @param {Function} fn optional An optional boolean test to apply. + * The optional function is passed the current DOM node being tested as its only argument. + * If no function is given, the parentNode is returned. + * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes. + * @return {HTMLElement | null} The matching DOM node or null if none found. + */ + // TODO: optional stopAt node? + ancestor: function(element, fn, all) { + return Y.DOM.elementByAxis(element, PARENT_NODE, fn, all); + }, + + /** + * Searches the element by the given axis for the first matching element. + * @method elementByAxis + * @param {HTMLElement} element The html element. + * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling). + * @param {Function} fn optional An optional boolean test to apply. + * @param {Boolean} all optional Whether all node types should be returned, or just element nodes. + * The optional function is passed the current HTMLElement being tested as its only argument. + * If no function is given, the first element is returned. + * @return {HTMLElement | null} The matching element or null if none found. + */ + elementByAxis: function(element, axis, fn, all) { + while (element && (element = element[axis])) { // NOTE: assignment + if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) { + return element; + } + } + return null; + }, + + /** + * Determines whether or not one HTMLElement is or contains another HTMLElement. + * @method contains + * @param {HTMLElement} element The containing html element. + * @param {HTMLElement} needle The html element that may be contained. + * @return {Boolean} Whether or not the element is or contains the needle. + */ + contains: function(element, needle) { + var ret = false; + + if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) { + ret = false; + } else if (element[CONTAINS]) { + if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE + ret = element[CONTAINS](needle); + } else { + ret = Y.DOM._bruteContains(element, needle); + } + } else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko + if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) { + ret = true; + } + } + + return ret; + }, + + /** + * Determines whether or not the HTMLElement is part of the document. + * @method inDoc + * @param {HTMLElement} element The containing html element. + * @param {HTMLElement} doc optional The document to check. + * @return {Boolean} Whether or not the element is attached to the document. + */ + inDoc: function(element, doc) { + doc = doc || element[OWNER_DOCUMENT]; + var id = element.id; + if (!id) { // TODO: remove when done? + id = element.id = Y.guid(); + } + + return !! (doc.getElementById(id)); + }, + + /** + * Creates a new dom node using the provided markup string. + * @method create + * @param {String} html The markup used to create the element + * @param {HTMLDocument} doc An optional document context + */ + create: function(html, doc) { + if (typeof html === 'string') { + html = Y.Lang.trim(html); // match IE which trims whitespace from innerHTML + } + + if (!doc && Y.DOM._cloneCache[html]) { + return Y.DOM._cloneCache[html].cloneNode(true); // NOTE: return + } + + doc = doc || Y.config.doc; + var m = re_tag.exec(html), + create = Y.DOM._create, + custom = Y.DOM.creators, + ret = null, + tag, nodes; + + if (m && custom[m[1]]) { + if (typeof custom[m[1]] === 'function') { + create = custom[m[1]]; + } else { + tag = custom[m[1]]; + } + } + + nodes = create(html, doc, tag).childNodes; + + if (nodes.length === 1) { // return single node, breaking parentNode ref from "fragment" + ret = nodes[0].parentNode.removeChild(nodes[0]); + } else { // return multiple nodes as a fragment + ret = Y.DOM._nl2frag(nodes, doc); + } + + if (ret) { + Y.DOM._cloneCache[html] = ret.cloneNode(true); + } + return ret; + }, + + _nl2frag: function(nodes, doc) { + var ret = null, + i, len; + + if (nodes && (nodes.push || nodes.item) && nodes[0]) { + doc = doc || nodes[0].ownerDocument; + ret = doc.createDocumentFragment(); + + if (nodes.item) { // convert live list to static array + nodes = Y.Array(nodes, 0, true); + } + + for (i = 0, len = nodes.length; i < len; i++) { + ret.appendChild(nodes[i]); + } + } // else inline with log for minification + return ret; + }, + + + CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8 + 'for': 'htmlFor', + 'class': 'className' + } : { // w3c + 'htmlFor': 'for', + 'className': 'class' + }, + + /** + * Provides a normalized attribute interface. + * @method setAttibute + * @param {String | HTMLElement} el The target element for the attribute. + * @param {String} attr The attribute to set. + * @param {String} val The value of the attribute. + */ + setAttribute: function(el, attr, val, ieAttr) { + if (el && el.setAttribute) { + attr = Y.DOM.CUSTOM_ATTRIBUTES[attr] || attr; + el.setAttribute(attr, val, ieAttr); + } + }, + + + /** + * Provides a normalized attribute interface. + * @method getAttibute + * @param {String | HTMLElement} el The target element for the attribute. + * @param {String} attr The attribute to get. + * @return {String} The current value of the attribute. + */ + getAttribute: function(el, attr, ieAttr) { + ieAttr = (ieAttr !== undefined) ? ieAttr : 2; + var ret = ''; + if (el && el.getAttribute) { + attr = Y.DOM.CUSTOM_ATTRIBUTES[attr] || attr; + ret = el.getAttribute(attr, ieAttr); + + if (ret === null) { + ret = ''; // per DOM spec + } + } + return ret; + }, + + isWindow: function(obj) { + return obj.alert && obj.document; + }, + + _fragClones: { + div: document.createElement('div') + }, + + _create: function(html, doc, tag) { + tag = tag || 'div'; + + var frag = Y.DOM._fragClones[tag]; + if (frag) { + frag = frag.cloneNode(false); + } else { + frag = Y.DOM._fragClones[tag] = doc.createElement(tag); + } + frag.innerHTML = html; + return frag; + }, + + _removeChildNodes: function(node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } + }, + + _cloneCache: {}, + + /** + * Inserts content in a node at the given location + * @method addHTML + * @param {HTMLElement} node The node to insert into + * @param {String} content The content to be inserted + * @param {String} where Where to insert the content; default is after lastChild + */ + addHTML: function(node, content, where) { + if (typeof content === 'string') { + content = Y.Lang.trim(content); // match IE which trims whitespace from innerHTML + } + + var newNode = Y.DOM._cloneCache[content], + nodeParent = node.parentNode; + + if (newNode) { + newNode = newNode.cloneNode(true); + } else { + if (content.nodeType) { // domNode + newNode = content; + } else { // create from string and cache + newNode = Y.DOM.create(content); + } + } + + if (where) { + if (where.nodeType) { // insert regardless of relationship to node + // TODO: check if node.contains(where)? + where.parentNode.insertBefore(newNode, where); + } else { + switch (where) { + case 'replace': + while (node.firstChild) { + node.removeChild(node.firstChild); + } + node.appendChild(newNode); + break; + case 'before': + nodeParent.insertBefore(newNode, node); + break; + case 'after': + if (node.nextSibling) { // IE errors if refNode is null + nodeParent.insertBefore(newNode, node.nextSibling); + } else { + nodeParent.appendChild(newNode); + } + break; + default: + node.appendChild(newNode); + } + } + } else { + node.appendChild(newNode); + } + + return newNode; + }, + + VALUE_SETTERS: {}, + + VALUE_GETTERS: {}, + + getValue: function(node) { + var ret = '', // TODO: return null? + getter; + + if (node && node[TAG_NAME]) { + getter = Y.DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()]; + + if (getter) { + ret = getter(node); + } else { + ret = node.value; + } + } + + return (typeof ret === 'string') ? ret : ''; + }, + + setValue: function(node, val) { + var setter; + + if (node && node[TAG_NAME]) { + setter = Y.DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()]; + + if (setter) { + setter(node, val); + } else { + node.value = val; + } + } + }, + + /** + * Brute force version of contains. + * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc). + * @method _bruteContains + * @private + * @param {HTMLElement} element The containing html element. + * @param {HTMLElement} needle The html element that may be contained. + * @return {Boolean} Whether or not the element is or contains the needle. + */ + _bruteContains: function(element, needle) { + while (needle) { + if (element === needle) { + return true; + } + needle = needle.parentNode; + } + return false; + }, + +// TODO: move to Lang? + /** + * Memoizes dynamic regular expressions to boost runtime performance. + * @method _getRegExp + * @private + * @param {String} str The string to convert to a regular expression. + * @param {String} flags optional An optinal string of flags. + * @return {RegExp} An instance of RegExp + */ + _getRegExp: function(str, flags) { + flags = flags || ''; + Y.DOM._regexCache = Y.DOM._regexCache || {}; + if (!Y.DOM._regexCache[str + flags]) { + Y.DOM._regexCache[str + flags] = new RegExp(str, flags); + } + return Y.DOM._regexCache[str + flags]; + }, + +// TODO: make getDoc/Win true privates? + /** + * returns the appropriate document. + * @method _getDoc + * @private + * @param {HTMLElement} element optional Target element. + * @return {Object} The document for the given element or the default document. + */ + _getDoc: function(element) { + element = element || {}; + + return (element[NODE_TYPE] === 9) ? element : // element === document + element[OWNER_DOCUMENT] || // element === DOM node + element.document || // element === window + Y.config.doc; // default + }, + + /** + * returns the appropriate window. + * @method _getWin + * @private + * @param {HTMLElement} element optional Target element. + * @return {Object} The window for the given element or the default window. + */ + _getWin: function(element) { + var doc = Y.DOM._getDoc(element); + return doc[DEFAULT_VIEW] || doc[PARENT_WINDOW] || Y.config.win; + }, + + _batch: function(nodes, fn, arg1, arg2, arg3, etc) { + fn = (typeof name === 'string') ? Y.DOM[fn] : fn; + var result, + ret = []; + + if (fn && nodes) { + Y.each(nodes, function(node) { + if ((result = fn.call(Y.DOM, node, arg1, arg2, arg3, etc)) !== undefined) { + ret[ret.length] = result; + } + }); + } + + return ret.length ? ret : nodes; + }, + + _testElement: function(element, tag, fn) { + tag = (tag && tag !== '*') ? tag.toUpperCase() : null; + return (element && element[TAG_NAME] && + (!tag || element[TAG_NAME].toUpperCase() === tag) && + (!fn || fn(element))); + }, + + creators: {}, + + _IESimpleCreate: function(html, doc) { + doc = doc || Y.config.doc; + return doc.createElement(html); + } +}; + + +(function(Y) { + var creators = Y.DOM.creators, + create = Y.DOM.create, + re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*
1 && tb && !re_tbody.test(html)) { + tb[PARENT_NODE].removeChild(tb); // strip extraneous tbody + } + return frag; + }, + + script: function(html, doc) { + var frag = doc.createElement('div'); + + frag.innerHTML = '-' + html; + frag.removeChild(frag[FIRST_CHILD]); + return frag; + } + + }, true); + + Y.mix(Y.DOM.VALUE_GETTERS, { + button: function(node) { + return (node.attributes && node.attributes.value) ? node.attributes.value.value : ''; + } + }); + + Y.mix(Y.DOM.VALUE_SETTERS, { + // IE: node.value changes the button text, which should be handled via innerHTML + button: function(node, val) { + var attr = node.attributes.value; + if (!attr) { + attr = node[OWNER_DOCUMENT].createAttribute('value'); + node.setAttributeNode(attr); + } + + attr.value = val; + } + }); + } + + if (Y.UA.gecko || Y.UA.ie) { + Y.mix(creators, { + option: function(html, doc) { + return create('', doc); + }, + + tr: function(html, doc) { + return create('' + html + '', doc); + }, + + td: function(html, doc) { + return create('