src/cm/media/js/lib/yui/yui3.0.0/build/dom/dom-base-debug.js
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     1 /*
       
     2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
       
     3 Code licensed under the BSD License:
       
     4 http://developer.yahoo.net/yui/license.txt
       
     5 version: 3.0.0
       
     6 build: 1549
       
     7 */
       
     8 YUI.add('dom-base', function(Y) {
       
     9 
       
    10 (function(Y) {
       
    11 /** 
       
    12  * The DOM utility provides a cross-browser abtraction layer
       
    13  * normalizing DOM tasks, and adds extra helper functionality
       
    14  * for other common tasks. 
       
    15  * @module dom
       
    16  * @submodule dom-base
       
    17  *
       
    18  */
       
    19 
       
    20 /**
       
    21  * Provides DOM helper methods.
       
    22  * @class DOM
       
    23  *
       
    24  */
       
    25 var NODE_TYPE = 'nodeType',
       
    26     OWNER_DOCUMENT = 'ownerDocument',
       
    27     DEFAULT_VIEW = 'defaultView',
       
    28     PARENT_WINDOW = 'parentWindow',
       
    29     TAG_NAME = 'tagName',
       
    30     PARENT_NODE = 'parentNode',
       
    31     FIRST_CHILD = 'firstChild',
       
    32     PREVIOUS_SIBLING = 'previousSibling',
       
    33     NEXT_SIBLING = 'nextSibling',
       
    34     CONTAINS = 'contains',
       
    35     COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
       
    36 
       
    37     documentElement = document.documentElement,
       
    38 
       
    39     re_tag = /<([a-z]+)/i;
       
    40 
       
    41 Y.DOM = {
       
    42     /**
       
    43      * Returns the HTMLElement with the given ID (Wrapper for document.getElementById).
       
    44      * @method byId         
       
    45      * @param {String} id the id attribute 
       
    46      * @param {Object} doc optional The document to search. Defaults to current document 
       
    47      * @return {HTMLElement | null} The HTMLElement with the id, or null if none found. 
       
    48      */
       
    49     byId: function(id, doc) {
       
    50         doc = doc || Y.config.doc;
       
    51         // TODO: IE Name
       
    52         return doc.getElementById(id);
       
    53     },
       
    54 
       
    55     // @deprecated
       
    56     children: function(node, tag) {
       
    57         var ret = [];
       
    58         if (node) {
       
    59             tag = tag || '*';
       
    60             ret = Y.Selector.query('> ' + tag, node); 
       
    61         }
       
    62         return ret;
       
    63     },
       
    64 
       
    65     // @deprecated
       
    66     firstByTag: function(tag, root) {
       
    67         var ret;
       
    68         root = root || Y.config.doc;
       
    69 
       
    70         if (tag && root.getElementsByTagName) {
       
    71             ret = root.getElementsByTagName(tag)[0];
       
    72         }
       
    73 
       
    74         return ret || null;
       
    75     },
       
    76 
       
    77     /**
       
    78      * Returns the text content of the HTMLElement. 
       
    79      * @method getText         
       
    80      * @param {HTMLElement} element The html element. 
       
    81      * @return {String} The text content of the element (includes text of any descending elements).
       
    82      */
       
    83     getText: (documentElement.textContent !== undefined) ?
       
    84         function(element) {
       
    85             var ret = '';
       
    86             if (element) {
       
    87                 ret = element.textContent;
       
    88             }
       
    89             return ret || '';
       
    90         } : function(element) {
       
    91             var ret = '';
       
    92             if (element) {
       
    93                 ret = element.innerText;
       
    94             }
       
    95             return ret || '';
       
    96         },
       
    97 
       
    98     /**
       
    99      * Sets the text content of the HTMLElement. 
       
   100      * @method setText         
       
   101      * @param {HTMLElement} element The html element. 
       
   102      * @param {String} content The content to add. 
       
   103      */
       
   104     setText: (documentElement.textContent !== undefined) ?
       
   105         function(element, content) {
       
   106             if (element) {
       
   107                 element.textContent = content;
       
   108             }
       
   109         } : function(element, content) {
       
   110             if (element) {
       
   111                 element.innerText = content;
       
   112             }
       
   113         },
       
   114 
       
   115     /*
       
   116      * Finds the previous sibling of the element.
       
   117      * @method previous
       
   118      * @deprecated Use elementByAxis
       
   119      * @param {HTMLElement} element The html element.
       
   120      * @param {Function} fn optional An optional boolean test to apply.
       
   121      * The optional function is passed the current DOM node being tested as its only argument.
       
   122      * If no function is given, the first sibling is returned.
       
   123      * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
       
   124      * @return {HTMLElement | null} The matching DOM node or null if none found. 
       
   125      */
       
   126     previous: function(element, fn, all) {
       
   127         return Y.DOM.elementByAxis(element, PREVIOUS_SIBLING, fn, all);
       
   128     },
       
   129 
       
   130     /*
       
   131      * Finds the next sibling of the element.
       
   132      * @method next
       
   133      * @deprecated Use elementByAxis
       
   134      * @param {HTMLElement} element The html element.
       
   135      * @param {Function} fn optional An optional boolean test to apply.
       
   136      * The optional function is passed the current DOM node being tested as its only argument.
       
   137      * If no function is given, the first sibling is returned.
       
   138      * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
       
   139      * @return {HTMLElement | null} The matching DOM node or null if none found. 
       
   140      */
       
   141     next: function(element, fn, all) {
       
   142         return Y.DOM.elementByAxis(element, NEXT_SIBLING, fn, all);
       
   143     },
       
   144 
       
   145     /*
       
   146      * Finds the ancestor of the element.
       
   147      * @method ancestor
       
   148      * @deprecated Use elementByAxis
       
   149      * @param {HTMLElement} element The html element.
       
   150      * @param {Function} fn optional An optional boolean test to apply.
       
   151      * The optional function is passed the current DOM node being tested as its only argument.
       
   152      * If no function is given, the parentNode is returned.
       
   153      * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
       
   154      * @return {HTMLElement | null} The matching DOM node or null if none found. 
       
   155      */
       
   156      // TODO: optional stopAt node?
       
   157     ancestor: function(element, fn, all) {
       
   158         return Y.DOM.elementByAxis(element, PARENT_NODE, fn, all);
       
   159     },
       
   160 
       
   161     /**
       
   162      * Searches the element by the given axis for the first matching element.
       
   163      * @method elementByAxis
       
   164      * @param {HTMLElement} element The html element.
       
   165      * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling).
       
   166      * @param {Function} fn optional An optional boolean test to apply.
       
   167      * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
       
   168      * The optional function is passed the current HTMLElement being tested as its only argument.
       
   169      * If no function is given, the first element is returned.
       
   170      * @return {HTMLElement | null} The matching element or null if none found.
       
   171      */
       
   172     elementByAxis: function(element, axis, fn, all) {
       
   173         while (element && (element = element[axis])) { // NOTE: assignment
       
   174                 if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
       
   175                     return element;
       
   176                 }
       
   177         }
       
   178         return null;
       
   179     },
       
   180 
       
   181     /**
       
   182      * Determines whether or not one HTMLElement is or contains another HTMLElement.
       
   183      * @method contains
       
   184      * @param {HTMLElement} element The containing html element.
       
   185      * @param {HTMLElement} needle The html element that may be contained.
       
   186      * @return {Boolean} Whether or not the element is or contains the needle.
       
   187      */
       
   188     contains: function(element, needle) {
       
   189         var ret = false;
       
   190 
       
   191         if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
       
   192             ret = false;
       
   193         } else if (element[CONTAINS])  {
       
   194             if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE
       
   195                 ret = element[CONTAINS](needle);
       
   196             } else {
       
   197                 ret = Y.DOM._bruteContains(element, needle); 
       
   198             }
       
   199         } else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko
       
   200             if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) { 
       
   201                 ret = true;
       
   202             }
       
   203         }
       
   204 
       
   205         return ret;
       
   206     },
       
   207 
       
   208     /**
       
   209      * Determines whether or not the HTMLElement is part of the document.
       
   210      * @method inDoc
       
   211      * @param {HTMLElement} element The containing html element.
       
   212      * @param {HTMLElement} doc optional The document to check.
       
   213      * @return {Boolean} Whether or not the element is attached to the document. 
       
   214      */
       
   215     inDoc: function(element, doc) {
       
   216         doc = doc || element[OWNER_DOCUMENT];
       
   217         var id = element.id;
       
   218         if (!id) { // TODO: remove when done?
       
   219             id = element.id = Y.guid();
       
   220         }
       
   221 
       
   222         return !! (doc.getElementById(id));
       
   223     },
       
   224 
       
   225     /**
       
   226      * Creates a new dom node using the provided markup string. 
       
   227      * @method create
       
   228      * @param {String} html The markup used to create the element
       
   229      * @param {HTMLDocument} doc An optional document context 
       
   230      */
       
   231     create: function(html, doc) {
       
   232         if (typeof html === 'string') {
       
   233             html = Y.Lang.trim(html); // match IE which trims whitespace from innerHTML
       
   234         }
       
   235 
       
   236         if (!doc && Y.DOM._cloneCache[html]) {
       
   237             return Y.DOM._cloneCache[html].cloneNode(true); // NOTE: return
       
   238         }
       
   239 
       
   240         doc = doc || Y.config.doc;
       
   241         var m = re_tag.exec(html),
       
   242             create = Y.DOM._create,
       
   243             custom = Y.DOM.creators,
       
   244             ret = null,
       
   245             tag, nodes;
       
   246 
       
   247         if (m && custom[m[1]]) {
       
   248             if (typeof custom[m[1]] === 'function') {
       
   249                 create = custom[m[1]];
       
   250             } else {
       
   251                 tag = custom[m[1]];
       
   252             }
       
   253         }
       
   254 
       
   255         nodes = create(html, doc, tag).childNodes;
       
   256 
       
   257         if (nodes.length === 1) { // return single node, breaking parentNode ref from "fragment"
       
   258             ret = nodes[0].parentNode.removeChild(nodes[0]);
       
   259         } else { // return multiple nodes as a fragment
       
   260              ret = Y.DOM._nl2frag(nodes, doc);
       
   261         }
       
   262 
       
   263         if (ret) {
       
   264             Y.DOM._cloneCache[html] = ret.cloneNode(true);
       
   265         }
       
   266         return ret;
       
   267     },
       
   268 
       
   269     _nl2frag: function(nodes, doc) {
       
   270         var ret = null,
       
   271             i, len;
       
   272 
       
   273         if (nodes && (nodes.push || nodes.item) && nodes[0]) {
       
   274             doc = doc || nodes[0].ownerDocument; 
       
   275             ret = doc.createDocumentFragment();
       
   276 
       
   277             if (nodes.item) { // convert live list to static array
       
   278                 nodes = Y.Array(nodes, 0, true);
       
   279             }
       
   280 
       
   281             for (i = 0, len = nodes.length; i < len; i++) {
       
   282                 ret.appendChild(nodes[i]); 
       
   283             }
       
   284         } // else inline with log for minification
       
   285         else { Y.log('unable to convert ' + nodes + ' to fragment', 'warn', 'dom'); }
       
   286         return ret;
       
   287     },
       
   288 
       
   289 
       
   290     CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
       
   291         'for': 'htmlFor',
       
   292         'class': 'className'
       
   293     } : { // w3c
       
   294         'htmlFor': 'for',
       
   295         'className': 'class'
       
   296     },
       
   297 
       
   298     /**
       
   299      * Provides a normalized attribute interface. 
       
   300      * @method setAttibute
       
   301      * @param {String | HTMLElement} el The target element for the attribute.
       
   302      * @param {String} attr The attribute to set.
       
   303      * @param {String} val The value of the attribute.
       
   304      */
       
   305     setAttribute: function(el, attr, val, ieAttr) {
       
   306         if (el && el.setAttribute) {
       
   307             attr = Y.DOM.CUSTOM_ATTRIBUTES[attr] || attr;
       
   308             el.setAttribute(attr, val, ieAttr);
       
   309         }
       
   310     },
       
   311 
       
   312 
       
   313     /**
       
   314      * Provides a normalized attribute interface. 
       
   315      * @method getAttibute
       
   316      * @param {String | HTMLElement} el The target element for the attribute.
       
   317      * @param {String} attr The attribute to get.
       
   318      * @return {String} The current value of the attribute. 
       
   319      */
       
   320     getAttribute: function(el, attr, ieAttr) {
       
   321         ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
       
   322         var ret = '';
       
   323         if (el && el.getAttribute) {
       
   324             attr = Y.DOM.CUSTOM_ATTRIBUTES[attr] || attr;
       
   325             ret = el.getAttribute(attr, ieAttr);
       
   326 
       
   327             if (ret === null) {
       
   328                 ret = ''; // per DOM spec
       
   329             }
       
   330         }
       
   331         return ret;
       
   332     },
       
   333 
       
   334     isWindow: function(obj) {
       
   335         return obj.alert && obj.document;
       
   336     },
       
   337 
       
   338     _fragClones: {
       
   339         div: document.createElement('div')
       
   340     },
       
   341 
       
   342     _create: function(html, doc, tag) {
       
   343         tag = tag || 'div';
       
   344 
       
   345         var frag = Y.DOM._fragClones[tag];
       
   346         if (frag) {
       
   347             frag = frag.cloneNode(false);
       
   348         } else {
       
   349             frag = Y.DOM._fragClones[tag] = doc.createElement(tag);
       
   350         }
       
   351         frag.innerHTML = html;
       
   352         return frag;
       
   353     },
       
   354 
       
   355     _removeChildNodes: function(node) {
       
   356         while (node.firstChild) {
       
   357             node.removeChild(node.firstChild);
       
   358         }
       
   359     },
       
   360 
       
   361     _cloneCache: {},
       
   362 
       
   363     /**
       
   364      * Inserts content in a node at the given location 
       
   365      * @method addHTML
       
   366      * @param {HTMLElement} node The node to insert into
       
   367      * @param {String} content The content to be inserted 
       
   368      * @param {String} where Where to insert the content; default is after lastChild 
       
   369      */
       
   370     addHTML: function(node, content, where) {
       
   371         if (typeof content === 'string') {
       
   372             content = Y.Lang.trim(content); // match IE which trims whitespace from innerHTML
       
   373         }
       
   374 
       
   375         var newNode = Y.DOM._cloneCache[content],
       
   376             nodeParent = node.parentNode;
       
   377             
       
   378         if (newNode) {
       
   379             newNode = newNode.cloneNode(true);
       
   380         } else {
       
   381             if (content.nodeType) { // domNode
       
   382                 newNode = content;
       
   383             } else { // create from string and cache
       
   384                 newNode = Y.DOM.create(content);
       
   385             }
       
   386         }
       
   387 
       
   388         if (where) {
       
   389             if (where.nodeType) { // insert regardless of relationship to node
       
   390                 // TODO: check if node.contains(where)?
       
   391                 where.parentNode.insertBefore(newNode, where);
       
   392             } else {
       
   393                 switch (where) {
       
   394                     case 'replace':
       
   395                         while (node.firstChild) {
       
   396                             node.removeChild(node.firstChild);
       
   397                         }
       
   398                         node.appendChild(newNode);
       
   399                         break;
       
   400                     case 'before':
       
   401                         nodeParent.insertBefore(newNode, node);
       
   402                         break;
       
   403                     case 'after':
       
   404                         if (node.nextSibling) { // IE errors if refNode is null
       
   405                             nodeParent.insertBefore(newNode, node.nextSibling);
       
   406                         } else {
       
   407                             nodeParent.appendChild(newNode);
       
   408                         }
       
   409                         break;
       
   410                     default:
       
   411                         node.appendChild(newNode);
       
   412                 }
       
   413             }
       
   414         } else {
       
   415             node.appendChild(newNode);
       
   416         }
       
   417 
       
   418         return newNode;
       
   419     },
       
   420 
       
   421     VALUE_SETTERS: {},
       
   422 
       
   423     VALUE_GETTERS: {},
       
   424 
       
   425     getValue: function(node) {
       
   426         var ret = '', // TODO: return null?
       
   427             getter;
       
   428 
       
   429         if (node && node[TAG_NAME]) {
       
   430             getter = Y.DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()];
       
   431 
       
   432             if (getter) {
       
   433                 ret = getter(node);
       
   434             } else {
       
   435                 ret = node.value;
       
   436             }
       
   437         }
       
   438 
       
   439         return (typeof ret === 'string') ? ret : '';
       
   440     },
       
   441 
       
   442     setValue: function(node, val) {
       
   443         var setter;
       
   444 
       
   445         if (node && node[TAG_NAME]) {
       
   446             setter = Y.DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()];
       
   447 
       
   448             if (setter) {
       
   449                 setter(node, val);
       
   450             } else {
       
   451                 node.value = val;
       
   452             }
       
   453         }
       
   454     },
       
   455 
       
   456     /**
       
   457      * Brute force version of contains.
       
   458      * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc).
       
   459      * @method _bruteContains
       
   460      * @private
       
   461      * @param {HTMLElement} element The containing html element.
       
   462      * @param {HTMLElement} needle The html element that may be contained.
       
   463      * @return {Boolean} Whether or not the element is or contains the needle.
       
   464      */
       
   465     _bruteContains: function(element, needle) {
       
   466         while (needle) {
       
   467             if (element === needle) {
       
   468                 return true;
       
   469             }
       
   470             needle = needle.parentNode;
       
   471         }
       
   472         return false;
       
   473     },
       
   474 
       
   475 // TODO: move to Lang?
       
   476     /**
       
   477      * Memoizes dynamic regular expressions to boost runtime performance. 
       
   478      * @method _getRegExp
       
   479      * @private
       
   480      * @param {String} str The string to convert to a regular expression.
       
   481      * @param {String} flags optional An optinal string of flags.
       
   482      * @return {RegExp} An instance of RegExp
       
   483      */
       
   484     _getRegExp: function(str, flags) {
       
   485         flags = flags || '';
       
   486         Y.DOM._regexCache = Y.DOM._regexCache || {};
       
   487         if (!Y.DOM._regexCache[str + flags]) {
       
   488             Y.DOM._regexCache[str + flags] = new RegExp(str, flags);
       
   489         }
       
   490         return Y.DOM._regexCache[str + flags];
       
   491     },
       
   492 
       
   493 // TODO: make getDoc/Win true privates?
       
   494     /**
       
   495      * returns the appropriate document.
       
   496      * @method _getDoc
       
   497      * @private
       
   498      * @param {HTMLElement} element optional Target element.
       
   499      * @return {Object} The document for the given element or the default document. 
       
   500      */
       
   501     _getDoc: function(element) {
       
   502         element = element || {};
       
   503 
       
   504         return (element[NODE_TYPE] === 9) ? element : // element === document
       
   505                 element[OWNER_DOCUMENT] || // element === DOM node
       
   506                 element.document || // element === window
       
   507                 Y.config.doc; // default
       
   508     },
       
   509 
       
   510     /**
       
   511      * returns the appropriate window.
       
   512      * @method _getWin
       
   513      * @private
       
   514      * @param {HTMLElement} element optional Target element.
       
   515      * @return {Object} The window for the given element or the default window. 
       
   516      */
       
   517     _getWin: function(element) {
       
   518         var doc = Y.DOM._getDoc(element);
       
   519         return doc[DEFAULT_VIEW] || doc[PARENT_WINDOW] || Y.config.win;
       
   520     },
       
   521 
       
   522     _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
       
   523         fn = (typeof name === 'string') ? Y.DOM[fn] : fn;
       
   524         var result,
       
   525             ret = [];
       
   526 
       
   527         if (fn && nodes) {
       
   528             Y.each(nodes, function(node) {
       
   529                 if ((result = fn.call(Y.DOM, node, arg1, arg2, arg3, etc)) !== undefined) {
       
   530                     ret[ret.length] = result;
       
   531                 }
       
   532             });
       
   533         }
       
   534 
       
   535         return ret.length ? ret : nodes;
       
   536     },
       
   537 
       
   538     _testElement: function(element, tag, fn) {
       
   539         tag = (tag && tag !== '*') ? tag.toUpperCase() : null;
       
   540         return (element && element[TAG_NAME] &&
       
   541                 (!tag || element[TAG_NAME].toUpperCase() === tag) &&
       
   542                 (!fn || fn(element)));
       
   543     },
       
   544 
       
   545     creators: {},
       
   546 
       
   547     _IESimpleCreate: function(html, doc) {
       
   548         doc = doc || Y.config.doc;
       
   549         return doc.createElement(html);
       
   550     }
       
   551 };
       
   552 
       
   553 
       
   554 (function(Y) {
       
   555     var creators = Y.DOM.creators,
       
   556         create = Y.DOM.create,
       
   557         re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,
       
   558 
       
   559         TABLE_OPEN = '<table>',
       
   560         TABLE_CLOSE = '</table>';
       
   561 
       
   562     if (Y.UA.ie) {
       
   563         Y.mix(creators, {
       
   564         // TODO: thead/tfoot with nested tbody
       
   565             // IE adds TBODY when creating TABLE elements (which may share this impl)
       
   566             tbody: function(html, doc) {
       
   567                 var frag = create(TABLE_OPEN + html + TABLE_CLOSE, doc),
       
   568                     tb = frag.children.tags('tbody')[0];
       
   569 
       
   570                 if (frag.children.length > 1 && tb && !re_tbody.test(html)) {
       
   571                     tb[PARENT_NODE].removeChild(tb); // strip extraneous tbody
       
   572                 }
       
   573                 return frag;
       
   574             },
       
   575 
       
   576             script: function(html, doc) {
       
   577                 var frag = doc.createElement('div');
       
   578 
       
   579                 frag.innerHTML = '-' + html;
       
   580                 frag.removeChild(frag[FIRST_CHILD]);
       
   581                 return frag;
       
   582             }
       
   583 
       
   584         }, true);
       
   585 
       
   586         Y.mix(Y.DOM.VALUE_GETTERS, {
       
   587             button: function(node) {
       
   588                 return (node.attributes && node.attributes.value) ? node.attributes.value.value : '';
       
   589             }
       
   590         });
       
   591 
       
   592         Y.mix(Y.DOM.VALUE_SETTERS, {
       
   593             // IE: node.value changes the button text, which should be handled via innerHTML
       
   594             button: function(node, val) {
       
   595                 var attr = node.attributes.value;
       
   596                 if (!attr) {
       
   597                     attr = node[OWNER_DOCUMENT].createAttribute('value');
       
   598                     node.setAttributeNode(attr);
       
   599                 }
       
   600 
       
   601                 attr.value = val;
       
   602             }
       
   603         });
       
   604     }
       
   605 
       
   606     if (Y.UA.gecko || Y.UA.ie) {
       
   607         Y.mix(creators, {
       
   608             option: function(html, doc) {
       
   609                 return create('<select>' + html + '</select>', doc);
       
   610             },
       
   611 
       
   612             tr: function(html, doc) {
       
   613                 return create('<tbody>' + html + '</tbody>', doc);
       
   614             },
       
   615 
       
   616             td: function(html, doc) {
       
   617                 return create('<tr>' + html + '</tr>', doc);
       
   618             }, 
       
   619 
       
   620             tbody: function(html, doc) {
       
   621                 return create(TABLE_OPEN + html + TABLE_CLOSE, doc);
       
   622             }
       
   623         });
       
   624 
       
   625         Y.mix(creators, {
       
   626             legend: 'fieldset',
       
   627             th: creators.td,
       
   628             thead: creators.tbody,
       
   629             tfoot: creators.tbody,
       
   630             caption: creators.tbody,
       
   631             colgroup: creators.tbody,
       
   632             col: creators.tbody,
       
   633             optgroup: creators.option
       
   634         });
       
   635     }
       
   636 
       
   637     Y.mix(Y.DOM.VALUE_GETTERS, {
       
   638         option: function(node) {
       
   639             var attrs = node.attributes;
       
   640             return (attrs.value && attrs.value.specified) ? node.value : node.text;
       
   641         },
       
   642 
       
   643         select: function(node) {
       
   644             var val = node.value,
       
   645                 options = node.options;
       
   646 
       
   647             if (options && val === '') {
       
   648                 if (node.multiple) {
       
   649                     Y.log('multiple select normalization not implemented', 'warn', 'DOM');
       
   650                 } else {
       
   651                     val = Y.DOM.getValue(options[node.selectedIndex], 'value');
       
   652                 }
       
   653             }
       
   654 
       
   655             return val;
       
   656         }
       
   657     });
       
   658 })(Y);
       
   659 
       
   660 })(Y);
       
   661 var addClass, hasClass, removeClass;
       
   662 
       
   663 Y.mix(Y.DOM, {
       
   664     /**
       
   665      * Determines whether a DOM element has the given className.
       
   666      * @method hasClass
       
   667      * @param {HTMLElement} element The DOM element. 
       
   668      * @param {String} className the class name to search for
       
   669      * @return {Boolean} Whether or not the element has the given class. 
       
   670      */
       
   671     hasClass: function(node, className) {
       
   672         var re = Y.DOM._getRegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
       
   673         return re.test(node.className);
       
   674     },
       
   675 
       
   676     /**
       
   677      * Adds a class name to a given DOM element.
       
   678      * @method addClass         
       
   679      * @param {HTMLElement} element The DOM element. 
       
   680      * @param {String} className the class name to add to the class attribute
       
   681      */
       
   682     addClass: function(node, className) {
       
   683         if (!Y.DOM.hasClass(node, className)) { // skip if already present 
       
   684             node.className = Y.Lang.trim([node.className, className].join(' '));
       
   685         }
       
   686     },
       
   687 
       
   688     /**
       
   689      * Removes a class name from a given element.
       
   690      * @method removeClass         
       
   691      * @param {HTMLElement} element The DOM element. 
       
   692      * @param {String} className the class name to remove from the class attribute
       
   693      */
       
   694     removeClass: function(node, className) {
       
   695         if (className && hasClass(node, className)) {
       
   696             node.className = Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
       
   697                             className + '(?:\\s+|$)'), ' '));
       
   698 
       
   699             if ( hasClass(node, className) ) { // in case of multiple adjacent
       
   700                 removeClass(node, className);
       
   701             }
       
   702         }                 
       
   703     },
       
   704 
       
   705     /**
       
   706      * Replace a class with another class for a given element.
       
   707      * If no oldClassName is present, the newClassName is simply added.
       
   708      * @method replaceClass  
       
   709      * @param {HTMLElement} element The DOM element. 
       
   710      * @param {String} oldClassName the class name to be replaced
       
   711      * @param {String} newClassName the class name that will be replacing the old class name
       
   712      */
       
   713     replaceClass: function(node, oldC, newC) {
       
   714         //Y.log('replaceClass replacing ' + oldC + ' with ' + newC, 'info', 'Node');
       
   715         addClass(node, newC);
       
   716         removeClass(node, oldC);
       
   717     },
       
   718 
       
   719     /**
       
   720      * If the className exists on the node it is removed, if it doesn't exist it is added.
       
   721      * @method toggleClass  
       
   722      * @param {HTMLElement} element The DOM element. 
       
   723      * @param {String} className the class name to be toggled
       
   724      */
       
   725     toggleClass: function(node, className) {
       
   726         if (hasClass(node, className)) {
       
   727             removeClass(node, className);
       
   728         } else {
       
   729             addClass(node, className);
       
   730         }
       
   731     }
       
   732 });
       
   733 
       
   734 hasClass = Y.DOM.hasClass;
       
   735 removeClass = Y.DOM.removeClass;
       
   736 addClass = Y.DOM.addClass;
       
   737 
       
   738 
       
   739 
       
   740 }, '3.0.0' ,{requires:['oop']});