dom.js revision 744aec5933ba55f438dc42a241edb3c95df5abff
3fde4c273ea649d1320ec9c51e7d096cd9340a94jerenkrantz * The DOM utility provides a cross-browser abtraction layer
3fde4c273ea649d1320ec9c51e7d096cd9340a94jerenkrantz * normalizing DOM tasks, and adds extra helper functionality
75eee56d2eaac9c27d32fc46b90bb6b1eac85359trawick * for other common tasks.
75eee56d2eaac9c27d32fc46b90bb6b1eac85359trawick * @module dom
0dc14774d2c21baf6123fcafdb853af5be1d97edwrowe * @submodule dom-base
9f62694a8b4e2b88994a14555d144b3836b311cfstoddard * Provides DOM helper methods.
9f62694a8b4e2b88994a14555d144b3836b311cfstoddard * @class DOM
eadb64379834961679105b7fd4178253fbb9f95dtrawick COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
c7e917aa56886c47bfe061c5e9f603a5aaef0d87trawickvar re_tag = /<([a-z]+)/i;
6b6083e6518007139257ee449c2af3032d2437d0trawick * Returns the HTMLElement with the given ID (Wrapper for document.getElementById).
6b6083e6518007139257ee449c2af3032d2437d0trawick * @method byId
6b6083e6518007139257ee449c2af3032d2437d0trawick * @param {String} id the id attribute
88dd056b9863502bba82c2889a0c4cde9fc0ba93trawick * @param {Object} doc optional The document to search. Defaults to current document
88dd056b9863502bba82c2889a0c4cde9fc0ba93trawick * @return {HTMLElement | null} The HTMLElement with the id, or null if none found.
1e83c8de3aa48b316b28057d53995272baf1260cwrowe * Returns the text content of the HTMLElement.
1e83c8de3aa48b316b28057d53995272baf1260cwrowe * @method getText
1e83c8de3aa48b316b28057d53995272baf1260cwrowe * @param {HTMLElement} element The html element.
1e83c8de3aa48b316b28057d53995272baf1260cwrowe * @return {String} The text content of the element (includes text of any descending elements).
7f683bb300df767164724ebc664f339ac396b434dougm * Finds the firstChild of the given HTMLElement.
7f683bb300df767164724ebc664f339ac396b434dougm * @method firstChild
26dfa083a1662d57ba7cc410eec4e0696b9be469wrowe * @param {HTMLElement} element The html element.
26dfa083a1662d57ba7cc410eec4e0696b9be469wrowe * @param {Function} fn optional An optional boolean test to apply.
26dfa083a1662d57ba7cc410eec4e0696b9be469wrowe * The optional function is passed the current HTMLElement being tested as its only argument.
26dfa083a1662d57ba7cc410eec4e0696b9be469wrowe * If no function is given, the first found is returned.
4760aa1f19600972cf531ad7da73c1ee5a0225cedougm * @return {HTMLElement | null} The first matching child html element.
525508562a53864b78cf8da91ac13be9c072bba7jerenkrantz * Finds the lastChild of the given HTMLElement.
525508562a53864b78cf8da91ac13be9c072bba7jerenkrantz * @method lastChild
f1fe10268cdadb775eef841aa4fa7305291d35fdtrawick * @param {HTMLElement} element The html element.
f1fe10268cdadb775eef841aa4fa7305291d35fdtrawick * @param {String} tag The tag to search for.
f1fe10268cdadb775eef841aa4fa7305291d35fdtrawick * @param {Function} fn optional An optional boolean test to apply.
f1fe10268cdadb775eef841aa4fa7305291d35fdtrawick * The optional function is passed the current HTMLElement being tested as its only argument.
f04ad0ba7fe0eea5ea7a92f852cef75747ab2090trawick * If no function is given, the first found is returned.
f04ad0ba7fe0eea5ea7a92f852cef75747ab2090trawick * @return {HTMLElement | null} The first matching child html element.
360a9d933a8c25f5975e0ddc883607a5d37e408estoddard * Finds all HTMLElement childNodes matching the given tag.
360a9d933a8c25f5975e0ddc883607a5d37e408estoddard * @method childrenByTag
360a9d933a8c25f5975e0ddc883607a5d37e408estoddard * @param {HTMLElement} element The html element.
9b8afc47122e9b0eabb860b6ba2cf9c061c6060fstoddard * @param {String} tag The tag to search for.
9b8afc47122e9b0eabb860b6ba2cf9c061c6060fstoddard * @param {Function} fn optional An optional boolean test to apply.
9b8afc47122e9b0eabb860b6ba2cf9c061c6060fstoddard * The optional function is passed the current HTMLElement being tested as its only argument.
9b8afc47122e9b0eabb860b6ba2cf9c061c6060fstoddard * If no function is given, all children with the given tag are collected.
a21148678a1459064627d917a66669e7e8d140e6stoddard * @return {Array} The collection of child elements.
910df8b3f50a0515b430b999d4750de94c509f2atrawick childrenByTag: function() {
c6a9d49433c9ba5b18b26c3d764f1bbcb9746090wrowe return function(element, tag, fn, toArray) { // TODO: keep toArray option?
bb6a7fc0427d0d197c50de34b94a0d23e5732696wrowe elements = (tag) ? element.children.tags(tag) : element.children;
e1753aabf5df187b5b04e72a958af4b65b1a125daaron tag = (tag && tag !== '*') ? tag.toUpperCase() : null;
924c8dd40352ca7775704a31a7a77ab86dc951b4ianh if (tag) { // wrap fn and add tag test TODO: allow tag in filterElementsBy?
910df8b3f50a0515b430b999d4750de94c509f2atrawick return el[TAG_NAME].toUpperCase() === tag && (!fn || fn(el));
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp * Finds all HTMLElement childNodes.
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp * @method children
185b73b1f914e5d8f99f31225cc656b882dcbf73ianh * @param {HTMLElement} element The html element.
6ef713e25735887d4a59a879b97a68bd575ecb92trawick * @param {Function} fn optional An optional boolean test to apply.
cef5cb47e2ea4c174c01762d4430613db0f41e5cstoddard * The optional function is passed the current HTMLElement being tested as its only argument.
cef5cb47e2ea4c174c01762d4430613db0f41e5cstoddard * If no function is given, all children are collected.
cef5cb47e2ea4c174c01762d4430613db0f41e5cstoddard * @return {Array} The collection of child elements.
6ef713e25735887d4a59a879b97a68bd575ecb92trawick * Finds the previous sibling of the element.
ca47a2b6bcea23e8af185c68f256dcbbfd2a0f9dtrawick * @method previous
26d590c0e5338f66ca1aad6f925374843fac5121stoddard * @param {HTMLElement} element The html element.
26d590c0e5338f66ca1aad6f925374843fac5121stoddard * @param {Function} fn optional An optional boolean test to apply.
26d590c0e5338f66ca1aad6f925374843fac5121stoddard * The optional function is passed the current DOM node being tested as its only argument.
26d590c0e5338f66ca1aad6f925374843fac5121stoddard * If no function is given, the first sibling is returned.
26d590c0e5338f66ca1aad6f925374843fac5121stoddard * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
2b31ac2c6342d2afcf67b7b0f08c928a87f98c74wrowe * @return {HTMLElement | null} The matching DOM node or null if none found.
d472f67198d6b15dd1270136f180cca9c9263243trawick return Y.DOM.elementByAxis(element, PREVIOUS_SIBLING, fn, all);
d472f67198d6b15dd1270136f180cca9c9263243trawick * Finds the next sibling of the element.
a3bb95a3600153c7f09f62749e32093658943c32brianp * @method next
a3bb95a3600153c7f09f62749e32093658943c32brianp * @param {HTMLElement} element The html element.
a3bb95a3600153c7f09f62749e32093658943c32brianp * @param {Function} fn optional An optional boolean test to apply.
b760518cc17e7124ba546ed63063603f1ab82a40aaron * The optional function is passed the current DOM node being tested as its only argument.
b760518cc17e7124ba546ed63063603f1ab82a40aaron * If no function is given, the first sibling is returned.
b760518cc17e7124ba546ed63063603f1ab82a40aaron * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
b760518cc17e7124ba546ed63063603f1ab82a40aaron * @return {HTMLElement | null} The matching DOM node or null if none found.
b760518cc17e7124ba546ed63063603f1ab82a40aaron return Y.DOM.elementByAxis(element, NEXT_SIBLING, fn, all);
23d8f62856c1531526042e1c5edf44557cadd2e5trawick * Finds the ancestor of the element.
705c8ed3ef608706c91ca12483d7b54ff9007cc9jerenkrantz * @method ancestor
705c8ed3ef608706c91ca12483d7b54ff9007cc9jerenkrantz * @param {HTMLElement} element The html element.
705c8ed3ef608706c91ca12483d7b54ff9007cc9jerenkrantz * @param {Function} fn optional An optional boolean test to apply.
ef154948c97c53cdc1ad5329cb83c32ad26cf416aaron * The optional function is passed the current DOM node being tested as its only argument.
ef154948c97c53cdc1ad5329cb83c32ad26cf416aaron * If no function is given, the parentNode is returned.
ef154948c97c53cdc1ad5329cb83c32ad26cf416aaron * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
c6741d11357aace4c9ba39535d3cb2d751f46114trawick * @return {HTMLElement | null} The matching DOM node or null if none found.
c6741d11357aace4c9ba39535d3cb2d751f46114trawick // TODO: optional stopAt node?
7230f1eb017a35b7d20e0e9ec0d234766f2a732dtrawick return Y.DOM.elementByAxis(element, PARENT_NODE, fn, all);
86a5d34400b7f586ad2cca97c8b33b2f55bac61btrawick * Searches the element by the given axis for the first matching element.
86a5d34400b7f586ad2cca97c8b33b2f55bac61btrawick * @method elementByAxis
86a5d34400b7f586ad2cca97c8b33b2f55bac61btrawick * @param {HTMLElement} element The html element.
86a5d34400b7f586ad2cca97c8b33b2f55bac61btrawick * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling).
86a5d34400b7f586ad2cca97c8b33b2f55bac61btrawick * @param {Function} fn optional An optional boolean test to apply.
6b477c0a238733ca8fd156629310513d29dc7e02trawick * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
6b477c0a238733ca8fd156629310513d29dc7e02trawick * The optional function is passed the current HTMLElement being tested as its only argument.
6b477c0a238733ca8fd156629310513d29dc7e02trawick * If no function is given, the first element is returned.
6b477c0a238733ca8fd156629310513d29dc7e02trawick * @return {HTMLElement | null} The matching element or null if none found.
557eb8d48357657fa898250560f089c65539c634gregames while (element && (element = element[axis])) { // NOTE: assignment
557eb8d48357657fa898250560f089c65539c634gregames if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
25b715e9687f82ea055fdea2a9761c7e5f1ac6eetrawick return null;
51ced3b28ef430a96586284d4320f7dbdaf7225ebrianp * Finds all elements with the given tag.
51ced3b28ef430a96586284d4320f7dbdaf7225ebrianp * @method byTag
a222035458f89e2db231450ba6d5fae8052da5f5aaron * @param {String} tag The tag being search for.
a222035458f89e2db231450ba6d5fae8052da5f5aaron * @param {HTMLElement} root optional An optional root element to start from.
a222035458f89e2db231450ba6d5fae8052da5f5aaron * @param {Function} fn optional An optional boolean test to apply.
a222035458f89e2db231450ba6d5fae8052da5f5aaron * The optional function is passed the current HTMLElement being tested as its only argument.
4a872628ca5bf20847f442a625c255b643120db0wrowe * If no function is given, all elements with the given tag are returned.
4a872628ca5bf20847f442a625c255b643120db0wrowe * @return {Array} The collection of matching elements.
f2afeedf074acc1a698a9527154eacd138e6c5a1trawick for (var i = 0, len = elements[LENGTH]; i < len; ++i) {
54b3b7946d22324cea615d7c8a4ff0c9eadd1f8crbb * Finds the first element with the given tag.
e28c02dc08247d3fcb71e81791cac2311a248dfdrbb * @method firstByTag
e28c02dc08247d3fcb71e81791cac2311a248dfdrbb * @param {String} tag The tag being search for.
e28c02dc08247d3fcb71e81791cac2311a248dfdrbb * @param {HTMLElement} root optional An optional root element to start from.
e28c02dc08247d3fcb71e81791cac2311a248dfdrbb * @param {Function} fn optional An optional boolean test to apply.
e28c02dc08247d3fcb71e81791cac2311a248dfdrbb * The optional function is passed the current HTMLElement being tested as its only argument.
e28c02dc08247d3fcb71e81791cac2311a248dfdrbb * If no function is given, the first match is returned.
e28c02dc08247d3fcb71e81791cac2311a248dfdrbb * @return {HTMLElement} The matching element.
9d0665da83d1e22c0ea0e5f6f940f70f75bf5237ianh for (var i = 0, len = elements[LENGTH]; i < len; ++i) {
0cdca1e056a05a09fe16fe736abcf79969c9767ejerenkrantz * Filters a collection of HTMLElements by the given attributes.
f2afeedf074acc1a698a9527154eacd138e6c5a1trawick * @method filterElementsBy
f2afeedf074acc1a698a9527154eacd138e6c5a1trawick * @param {Array} elements The collection of HTMLElements to filter.
f2afeedf074acc1a698a9527154eacd138e6c5a1trawick * @param {Function} fn A boolean test to apply.
0a2d57d962bef3a8898723925b3fb02d2e836994dougm * The function is passed the current HTMLElement being tested as its only argument.
0a2d57d962bef3a8898723925b3fb02d2e836994dougm * If no function is given, all HTMLElements are kept.
2a20a2f8432a15b530e0a6b0998c32f40aef82a8gregames * @return {Array} The filtered collection of HTMLElements.
06461d67f387ea068187e6dfa036875a8205c04cjerenkrantz filterElementsBy: function(elements, fn, firstOnly) {
900127764fb985c340ee4979cac97146a330c694trawick for (var i = 0, len = elements[LENGTH]; i < len; ++i) {
1a6a0072a95887164091e366ba0e89c2b39a954abrianp if (elements[i][TAG_NAME] && (!fn || fn(elements[i]))) {
97719ad970d779ac48af9364ab0ea9fdcc27470ajwoolley * Determines whether or not one HTMLElement is or contains another HTMLElement.
5ad238c42b1e159ee8f164515e0c4ee6c727c2fdtrawick * @method contains
5ad238c42b1e159ee8f164515e0c4ee6c727c2fdtrawick * @param {HTMLElement} element The containing html element.
5ad238c42b1e159ee8f164515e0c4ee6c727c2fdtrawick * @param {HTMLElement} needle The html element that may be contained.
ba00c3b7c20f00ce631b89ae3b1cd3bae8d1b165rbb * @return {Boolean} Whether or not the element is or contains the needle.
ba00c3b7c20f00ce631b89ae3b1cd3bae8d1b165rbb var ret = false;
ba00c3b7c20f00ce631b89ae3b1cd3bae8d1b165rbb if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
6e954603b02f2b7d4ad80af17d9b3cc6f0bacf69rbb if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE
6e954603b02f2b7d4ad80af17d9b3cc6f0bacf69rbb } else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko
fa449f5bc87c5d87c4c60e778c9c882e7254de7ejwoolley if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) {
227d23a7db41dd89f52391c9356dbb1adcd675e0jwoolley * Determines whether or not the HTMLElement is part of the document.
227d23a7db41dd89f52391c9356dbb1adcd675e0jwoolley * @method inDoc
227d23a7db41dd89f52391c9356dbb1adcd675e0jwoolley * @param {HTMLElement} element The containing html element.
1c0b7c3bdace07946457fa7ba04b7f97b6599792rbb * @param {HTMLElement} doc optional The document to check.
17bc0e8f2e3816e25bc8fd3fadf39357340aebd0jerenkrantz * @return {Boolean} Whether or not the element is attached to the document.
17bc0e8f2e3816e25bc8fd3fadf39357340aebd0jerenkrantz return Y.DOM.contains(doc.documentElement, element);
e6cc28a5eb3371ba0c38e941855e71ff0054f50erbb// TODO: dont return collection
2a20a2f8432a15b530e0a6b0998c32f40aef82a8gregames return (ret.childNodes.length > 1) ? ret.childNodes : ret.childNodes[0]; // collection or item
2a20a2f8432a15b530e0a6b0998c32f40aef82a8gregames //return ret.firstChild;
2a20a2f8432a15b530e0a6b0998c32f40aef82a8gregames CUSTOM_ATTRIBUTES: (!document.documentElement.hasAttribute) ? { // IE < 8
f99bffd6087564cf9c05cc29d1c6b38d94e0ed30gregames } : { // w3c
8458877c9ba0af86acd590eea531476adde3d02dmartin * Provides a normalized attribute interface.
8458877c9ba0af86acd590eea531476adde3d02dmartin * @method setAttibute
8458877c9ba0af86acd590eea531476adde3d02dmartin * @param {String | HTMLElement} el The target element for the attribute.
644be6f54749d2d9950d2c4d2ac448f7af016d26martin * @param {String} attr The attribute to set.
644be6f54749d2d9950d2c4d2ac448f7af016d26martin * @param {String} val The value of the attribute.
c4fbc4018fd2b6716673a38ee27eeb36cba41c5djwoolley * Provides a normalized attribute interface.
c4fbc4018fd2b6716673a38ee27eeb36cba41c5djwoolley * @method getAttibute
f4e4643c309e5b5da60e13f9a25984d54b307caawrowe * @param {String | HTMLElement} el The target element for the attribute.
f4e4643c309e5b5da60e13f9a25984d54b307caawrowe * @param {String} attr The attribute to get.
f4e4643c309e5b5da60e13f9a25984d54b307caawrowe * @return {String} The current value of the attribute.
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz if (!document.documentElement.hasAttribute) { // IE < 8
9126ed10455a2a98a3a51c68ed1b356e1873e8e6aaron if (ret === null) {
18acb2c0df442ead1d075a1a2207cbb197725b14coar var frag = templateCache[tag] || doc.createElement(tag);
617f972690d850a52cd4e9ef2f32d356e0fae715aaron * Brute force version of contains.
617f972690d850a52cd4e9ef2f32d356e0fae715aaron * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc).
617f972690d850a52cd4e9ef2f32d356e0fae715aaron * @method _bruteContains
9278d5393ef084f4fc6d7ec8641af5959442c157jwoolley * @param {HTMLElement} element The containing html element.
9278d5393ef084f4fc6d7ec8641af5959442c157jwoolley * @param {HTMLElement} needle The html element that may be contained.
022cff78006f698453640e0a0e97cc5f8c9de59drbb * @return {Boolean} Whether or not the element is or contains the needle.
526a776292f420ffeea0d081c61971ed381fad20stoddard return true;
526a776292f420ffeea0d081c61971ed381fad20stoddard return false;
526a776292f420ffeea0d081c61971ed381fad20stoddard// TODO: move to Lang?
526a776292f420ffeea0d081c61971ed381fad20stoddard * Memoizes dynamic regular expressions to boost runtime performance.
452d2fd15cebd2da9331d5d765558a60b488c1a9rbb * @method _getRegExp
62ddc9851530478919d169ba9c34b80f60cf7718trawick * @param {String} str The string to convert to a regular expression.
62ddc9851530478919d169ba9c34b80f60cf7718trawick * @param {String} flags optional An optinal string of flags.
62ddc9851530478919d169ba9c34b80f60cf7718trawick * @return {RegExp} An instance of RegExp
904d7bf799c6216beb34519463596b4fce630308wrowe Y.DOM._regexCache[str + flags] = new RegExp(str, flags);
17a4c6968b2fa692ff4dde12fe305230ee6b0421aaron// TODO: make getDoc/Win true privates?
17a4c6968b2fa692ff4dde12fe305230ee6b0421aaron * returns the appropriate document.
17a4c6968b2fa692ff4dde12fe305230ee6b0421aaron * @method _getDoc
83b031099aa3dc8a5fd2f708e397818cbd16c9aajerenkrantz * @param {HTMLElement} element optional Target element.
83b031099aa3dc8a5fd2f708e397818cbd16c9aajerenkrantz * @return {Object} The document for the given element or the default document.
8ea9794272347cfdd92861f46295406649f01afatrawick return (element[NODE_TYPE] === 9) ? element : // element === document
b900452c9c36031434d318880f023c0fb9143325rbb * returns the appropriate window.
b900452c9c36031434d318880f023c0fb9143325rbb * @method _getWin
b900452c9c36031434d318880f023c0fb9143325rbb * @private
b900452c9c36031434d318880f023c0fb9143325rbb * @param {HTMLElement} element optional Target element.
b900452c9c36031434d318880f023c0fb9143325rbb * @return {Object} The window for the given element or the default window.
c453a141db60a5b19649eac508f4851a8729c556rbb return doc[DEFAULT_VIEW] || doc[PARENT_WINDOW] || Y.config.win;
8b91dcac0e1ef7796c72d16b0962267313cac486jerenkrantz // TODO: document this
6ce942b017db75b559a42bdc2d7b8ea9e869a956wrowe var ret = null,
574f6ff9ee80ef4f772649c5c8319b764a8abe42jerenkrantz if (Y.DOM._testElement(root, tag, fn)) { // is the matching element
574f6ff9ee80ef4f772649c5c8319b764a8abe42jerenkrantz } else { // need to scan nextSibling axis of firstChild to find matching element
a310497ca9c5112d759871e1b7d9f6a40fb78bcfwrowe tag = (tag && tag !== '*') ? tag.toUpperCase() : null;
e36ef0d081aa59867688bcbb3da65952ec16fae3rbb(function() {
e36ef0d081aa59867688bcbb3da65952ec16fae3rbb re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/;
2c294c31addd5c957bafe6e78c4a30d423ad6e80rbb if (Y.UA.gecko || Y.UA.ie) { // require custom creation code for certain element types
44a4ee1140769173da7bc2b42d1a686e3260ad84wrowe var frag = creators.tbody('<tbody>' + html + '</tbody>', doc);
e379fc6d7f79163700290d92ce75deb4f3005301jerenkrantz var frag = creators.tr('<tr>' + html + '</tr>', doc);
978faa9e29e0f0c42e66c07240e562325a4717b0jerenkrantz var frag = create(TABLE_OPEN + html + TABLE_CLOSE, doc);
10a00688adcf1df367b1243810beedaabe6b1abeminfrin creators.col = creators.tbody; // IE wraps in colgroup
8a3a703eae0e35f674b189181609545c6fc77a09rbb // TODO: allow multiples ("<link><link>")
8a3a703eae0e35f674b189181609545c6fc77a09rbb creators.col = creators.script = creators.link = Y.DOM._IESimpleCreate;
9af1ccb223d0669b3c3a43eed070d815afde9084mjc // TODO: thead/tfoot with nested tbody
9af1ccb223d0669b3c3a43eed070d815afde9084mjc var frag = create(TABLE_OPEN + html + TABLE_CLOSE, doc);
9d41fafe32b324c197f25224207fc6ce34f085bfrbb if (frag.children.length > 1 && tb && !re_tbody.test(html)) {
8c83461e53ca7d204e1d634f0c78199d60320d7bjerenkrantz if (Y.UA.gecko || Y.UA.ie) { // require custom creation code for certain element types
abaaa634d7cee882b7c4bf078ded749ebf11997erbb * The DOM utility provides a cross-browser abtraction layer
abaaa634d7cee882b7c4bf078ded749ebf11997erbb * normalizing DOM tasks, and adds extra helper functionality
0aa8e8fd5a242948518655f2296b3c76386754e5jerenkrantz * for other common tasks.
0aa8e8fd5a242948518655f2296b3c76386754e5jerenkrantz * @module dom
0aa8e8fd5a242948518655f2296b3c76386754e5jerenkrantz * @submodule dom-base
de3abad1fe263e577bb11e99b358836bd901397crbb * @for DOM
de3abad1fe263e577bb11e99b358836bd901397crbb * Determines whether a DOM element has the given className.
de3abad1fe263e577bb11e99b358836bd901397crbb * @method hasClass
0a549489abdb309ef25483431e1e5610ed4ba7a8gstein * @param {HTMLElement} element The DOM element.
0a549489abdb309ef25483431e1e5610ed4ba7a8gstein * @param {String} className the class name to search for
0a549489abdb309ef25483431e1e5610ed4ba7a8gstein * @return {Boolean} Whether or not the element has the given class.
0a549489abdb309ef25483431e1e5610ed4ba7a8gstein var re = Y.DOM._getRegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
f00d1e76bae896c2f6a520eec69b1d0d802d4108jerenkrantz * Adds a class name to a given DOM element.
f00d1e76bae896c2f6a520eec69b1d0d802d4108jerenkrantz * @method addClass
f00d1e76bae896c2f6a520eec69b1d0d802d4108jerenkrantz * @param {HTMLElement} element The DOM element.
58097d7d8d1a394092374b9f6ddf76b7993724a4rbb * @param {String} className the class name to add to the class attribute
58097d7d8d1a394092374b9f6ddf76b7993724a4rbb if (!Y.DOM.hasClass(node, className)) { // skip if already present
2f6cebd6b8bf0b044f6579d23117a4a3c364a554wrowe node[CLASS_NAME] = Y.Lang.trim([node[CLASS_NAME], className].join(' '));
070d2f9fd52a3f0e45ca7ae1235c5a5755b80d24rbb * Removes a class name from a given element.
070d2f9fd52a3f0e45ca7ae1235c5a5755b80d24rbb * @method removeClass
070d2f9fd52a3f0e45ca7ae1235c5a5755b80d24rbb * @param {HTMLElement} element The DOM element.
070d2f9fd52a3f0e45ca7ae1235c5a5755b80d24rbb * @param {String} className the class name to remove from the class attribute
7c19ce86bbd72bba1d018522250f5f315ffbc0afjerenkrantz if (className && Y.DOM.hasClass(node, className)) {
7c19ce86bbd72bba1d018522250f5f315ffbc0afjerenkrantz node[CLASS_NAME] = Y.Lang.trim(node[CLASS_NAME].replace(Y.DOM._getRegExp('(?:^|\\s+)' +
2264fbcbab4c796c4222c30393c0b218c98b6befrbb if ( Y.DOM.hasClass(node, className) ) { // in case of multiple adjacent
9b29e0cfeb2c89a047806cc4a2a764afed6bb170wrowe * Replace a class with another class for a given element.
9b29e0cfeb2c89a047806cc4a2a764afed6bb170wrowe * If no oldClassName is present, the newClassName is simply added.
441bd066858500e75e4f63ef149120bcf523de58jerenkrantz * @method replaceClass
441bd066858500e75e4f63ef149120bcf523de58jerenkrantz * @param {HTMLElement} element The DOM element.
441bd066858500e75e4f63ef149120bcf523de58jerenkrantz * @param {String} oldClassName the class name to be replaced
d6a93816bfaa5b3de5f2e6cb0d172cbe20dd056ejerenkrantz * @param {String} newClassName the class name that will be replacing the old class name
c839614b4216fe34f6346668ad646aca2c0f23c6wrowe * If the className exists on the node it is removed, if it doesn't exist it is added.
117e2968318323d2ad2187fcd4de379d2eca245cwrowe * @method toggleClass
117e2968318323d2ad2187fcd4de379d2eca245cwrowe * @param {HTMLElement} element The DOM element.
117e2968318323d2ad2187fcd4de379d2eca245cwrowe * @param {String} className the class name to be toggled
e9fa5a00f39f6aabbc5dcd776c5bc6bd0638f955wrowe * Add style management functionality to DOM.
e9fa5a00f39f6aabbc5dcd776c5bc6bd0638f955wrowe * @module dom
e9fa5a00f39f6aabbc5dcd776c5bc6bd0638f955wrowe * @submodule dom-style
7ba1a2c8babfd7c7c46bb03567a868d51e1023dbwrowe * Sets a style property for a given element.
b2c2c8a4bc977c0a6bb937af995efc56dc3879a3wrowe * @method setStyle
b2c2c8a4bc977c0a6bb937af995efc56dc3879a3wrowe * @param {HTMLElement} An HTMLElement to apply the style to.
b2c2c8a4bc977c0a6bb937af995efc56dc3879a3wrowe * @param {String} att The style property to set.
b2c2c8a4bc977c0a6bb937af995efc56dc3879a3wrowe * @param {String|Number} val The value.
e00ae6859667e293a4c40108f524408ae1289f2frbb return; // NOTE: return
0db1b9810f06c0e3c537e0e0dfbc30160c308526trawick } else if (typeof CUSTOM_STYLES[att] === 'string') {
053497224246c4dbef9af594cacf5c00ed271e6cwrowe * Returns the current style value for the given property.
053497224246c4dbef9af594cacf5c00ed271e6cwrowe * @method getStyle
ac06e54654494445fd3d39e90bd23b436b4f84ccwrowe * @param {HTMLElement} An HTMLElement to get the style from.
ac06e54654494445fd3d39e90bd23b436b4f84ccwrowe * @param {String} att The style property to get.
78e8198247420a3efeb21e38b42c423e5863cbb0jwoolley return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe if (val === '') { // TODO: is empty string sufficient?
7f66c5be12d3b48b1ebfa79033c099e4f91ff302dougm * Sets multiple style properties.
7f66c5be12d3b48b1ebfa79033c099e4f91ff302dougm * @method setStyles
7f66c5be12d3b48b1ebfa79033c099e4f91ff302dougm * @param {HTMLElement} node An HTMLElement to apply the styles to.
7f66c5be12d3b48b1ebfa79033c099e4f91ff302dougm * @param {Object} hash An object literal of property:value pairs.
53b8cdb3621b11b897438d8990d20e0b78f0d4b7rederpj * Returns the computed style for the given node.
53b8cdb3621b11b897438d8990d20e0b78f0d4b7rederpj * @method getComputedStyle
53b8cdb3621b11b897438d8990d20e0b78f0d4b7rederpj * @param {HTMLElement} An HTMLElement to get the style from.
53b8cdb3621b11b897438d8990d20e0b78f0d4b7rederpj * @param {String} att The style property to get.
53b8cdb3621b11b897438d8990d20e0b78f0d4b7rederpj * @return {String} The computed value of the style property.
6b025bd5a034790b2bb31236092265e154d6a565dougm val = doc[DEFAULT_VIEW][GET_COMPUTED_STYLE](node, '')[att];
91cbefdfe308c93892b52045a5f0253506432cd0trawick// normalize reserved word float alternatives ("cssFloat" or "styleFloat")
91cbefdfe308c93892b52045a5f0253506432cd0trawickif (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== UNDEFINED) {
598ce99543701a45a31bb01bf73c83d894592491rederpj} else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== UNDEFINED) {
fa687651463b68c7cc0dda80341712d1ef9543efwrowe// fix opera computedStyle default color unit (convert to rgb)
1fff95696a94273a1629649652cbc5d2e9e8ce39minfrin// safari converts transparent to rgba(), others use "transparent"
7a027a168069a89ca0946e04294f5130d9cbe3b8rederpj * Adds position and region management functionality to DOM.
29caf394750ea44e25d289a9aa7b92b9823faa8aminfrin * @module dom
29caf394750ea44e25d289a9aa7b92b9823faa8aminfrin * @submodule dom-screen
bb5c04f1ab6c2913d49b263e26302c748a1aa70btrawick // TODO: does caption matter?
50e228f0b8429c27e411611f4863fafaba403b47wrowe * Returns the inner height of the viewport (exludes scrollbar).
50e228f0b8429c27e411611f4863fafaba403b47wrowe * @method winHeight
7ba58e7e63da9a8b84f6160c476a0c9d639c81e9trawick * Returns the inner width of the viewport (exludes scrollbar).
0315d8e436a65aa1fd145ce0a84f6c0f21e304c0wrowe * @method winWidth
496dc24432cc5c9f95a627865879d4b83dca1055coar * Document height
5b5d90c6d3ffb9e28a62c6bc8e2cb60e4740f7f7coar * @method docHeight
622f0f22cd52de0e9904b218defdeb3181e113f3trawick return Math.max(h, Y.DOM._getWinSize(node)[HEIGHT]);
e83476358ef015a1959284421fdc25ab18a7aa02rbb * Document width
7b4c4bb891261e613de39a021d7554fd08132fc5rbb * @method docWidth
4c6731b2f737f8d7fcacd44b97d9e6bab745f1a5rbb * Amount page has been scroll vertically
0917cf91e713579b7ee0b03e499a08d7c3ec2d88rbb * @method docScrollX
0917cf91e713579b7ee0b03e499a08d7c3ec2d88rbb return Math.max(doc[DOCUMENT_ELEMENT][SCROLL_LEFT], doc.body[SCROLL_LEFT]);
251b60354534e12b004603ecf2a83f32756dc885rbb * Amount page has been scroll horizontally
251b60354534e12b004603ecf2a83f32756dc885rbb * @method docScrollY
251b60354534e12b004603ecf2a83f32756dc885rbb return Math.max(doc[DOCUMENT_ELEMENT][SCROLL_TOP], doc.body[SCROLL_TOP]);
12348d5b520522b6581d907ef9c1ceda029fbc05rbb * Gets the current position of an element based on page coordinates.
12348d5b520522b6581d907ef9c1ceda029fbc05rbb * Element must be part of the DOM tree to have page coordinates
a3b2a05c4c0f6a29e75c9349b85640192f6a8bfejwoolley * (display:none or elements not appended return false).
f8b7801ea5717ef22cc0d02bffacfd5f9e48f898gregames * @method getXY
d65b067e7797b56d6678b0ddcd0aa9258cd55e64trawick * @param element The target element
d65b067e7797b56d6678b0ddcd0aa9258cd55e64trawick * @return {Array} The XY position of the element
f947ecf8a772cbfcce0315feb68ad88e84299ad0trawick getXY: function() {
f947ecf8a772cbfcce0315feb68ad88e84299ad0trawick if (document[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
f947ecf8a772cbfcce0315feb68ad88e84299ad0trawick return function(node) {
82efd02118af953c3840478fa5e979a4194a579fwrowe return false;
82efd02118af953c3840478fa5e979a4194a579fwrowe //Round the numbers so we get sane data back
82efd02118af953c3840478fa5e979a4194a579fwrowe bLeft = Y.DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_LEFT_WIDTH),
82efd02118af953c3840478fa5e979a4194a579fwrowe bTop = Y.DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_TOP_WIDTH);
dc96a5e6f9af3c514df4c61ab9468fcf97f9846fwrowe // gecko may return sub-pixel (non-int) values
dc96a5e6f9af3c514df4c61ab9468fcf97f9846fwrowe return function(node) { // manually calculate by crawling up offsetParents
731c41a39b8273a6c4b8b87b6fd0ba5c7f3f9e2bwrowe //Calculate the Top and Left border sizes (assumes pixels)
cd32ea298a494089c6886c8de0e8ad13ddc7ee6cwrowe // TODO: refactor with !! or just falsey
dc96a5e6f9af3c514df4c61ab9468fcf97f9846fwrowe bCheck = ((Y.UA.gecko || Y.UA.webkit > 519) ? true : false);
cd32ea298a494089c6886c8de0e8ad13ddc7ee6cwrowe // TODO: worth refactoring for TOP/LEFT only?
e49758465fbf67f29f9aeda996d09f7cc6fa9fe5rbb // account for any scrolled ancestors
62db15de4c1f335a64d45821796ae197cff94ef8rbb //Firefox does something funky with borders when overflow is not visible.
62db15de4c1f335a64d45821796ae197cff94ef8rbb if (Y.UA.gecko && (Y.DOM.getStyle(parentNode, 'overflow') !== 'visible')) {
f8b7801ea5717ef22cc0d02bffacfd5f9e48f898gregames //Fix FIXED position -- add scrollbars
b1627fe7e2cb3809dcdfdf1fcbbb6dbccaf788c6rbb //Round the numbers so we get sane data back
06c2a9f9fcea4b8a21d6b7ffdd50c7a40edf10ffgregames }(),// NOTE: Executing for loadtime branching
263dbbd9c2a6952e756973b3dde9beeaf8eff6b7gregames * Gets the current X position of an element based on page coordinates.
6529086e53a38486d6cf0eac256b96548b6ef299wrowe * Element must be part of the DOM tree to have page coordinates
6529086e53a38486d6cf0eac256b96548b6ef299wrowe * (display:none or elements not appended return false).
6529086e53a38486d6cf0eac256b96548b6ef299wrowe * @method getX
6529086e53a38486d6cf0eac256b96548b6ef299wrowe * @param element The target element
6529086e53a38486d6cf0eac256b96548b6ef299wrowe * @return {Int} The X position of the element
9876642ec8126175f143702d7b949643f8128fdftrawick * Gets the current Y position of an element based on page coordinates.
263dbbd9c2a6952e756973b3dde9beeaf8eff6b7gregames * Element must be part of the DOM tree to have page coordinates
263dbbd9c2a6952e756973b3dde9beeaf8eff6b7gregames * (display:none or elements not appended return false).
263dbbd9c2a6952e756973b3dde9beeaf8eff6b7gregames * @method getY
263dbbd9c2a6952e756973b3dde9beeaf8eff6b7gregames * @param element The target element
0f2ac39337f7543f197db8b040f596123167eb2dstoddard * @return {Int} The Y position of the element
5183e10e45a86e2dd1112a4d71c24db3facbbc9agregames * Set the position of an html element in page coordinates.
0f2ac39337f7543f197db8b040f596123167eb2dstoddard * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
4ff47e3535a6da266acc3f0cf743046dbf16a856rbb * @method setXY
afab3e893c3fecabf2e3cac4e37ada58db984cearbb * @param element The target element
afab3e893c3fecabf2e3cac4e37ada58db984cearbb * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
afab3e893c3fecabf2e3cac4e37ada58db984cearbb * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
612ea048caf897cb6e69dc296d2b143a08ba83a0rbb delta = [ // assuming pixels; if not we will have to retry
30309f86bfd564437654aa822a19cd0cb29ca6f8wrowe if (currentXY === false) { // has to be part of doc to have xy
65db4f712167a3498de73cee5c08032a8aa6a010rbb return false;
ed4f9ec869d7fc5bd220c8d70ee58eed9b32d60arederpj delta[1] = (pos == RELATIVE) ? 0 : node[OFFSET_TOP];
c8af62b87a118cbbc25414eb9459219f338b1b0fstoddard setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px');
c8af62b87a118cbbc25414eb9459219f338b1b0fstoddard setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px');
8f43c3299e44dc11a4cd68acc93b578a0318daaftrawick // if retry is true, try one more time if we miss
688f7d0bc138bb02f92288017920468e7e314f23stoddard * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
688f7d0bc138bb02f92288017920468e7e314f23stoddard * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
688f7d0bc138bb02f92288017920468e7e314f23stoddard * @method setX
688f7d0bc138bb02f92288017920468e7e314f23stoddard * @param element The target element
688f7d0bc138bb02f92288017920468e7e314f23stoddard * @param {Int} x The X values for new position (coordinates are page-based)
9180a5933673ffb1af633c255ceee029340f3b1erbb * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
448a83963e3ec557bc9f9020ab44f9681595d1eerbb * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
e654452796751e21828a4078767e075eccf3b232stoddard * @method setY
e654452796751e21828a4078767e075eccf3b232stoddard * @param element The target element
e654452796751e21828a4078767e075eccf3b232stoddard * @param {Int} y The Y values for new position (coordinates are page-based)
cf293fe6e2515d89788ec515ce6266ad6f13a724stoddard var t = parseInt(Y.DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0,
f91cd1fc44d2588d82a56570b1005e7310dfc970jwoolley l = parseInt(Y.DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0;
e14ec68ef48bbf6c3dc567900f9e087eaf0bc931trawick return { height: root.scrollHeight, width: root.scrollWidth };
227e0bfd39e7c757d3618c8ada78d80cd1143d32wrowe * Adds position and region management functionality to DOM.
227e0bfd39e7c757d3618c8ada78d80cd1143d32wrowe * @module dom
8ff9257331986cb3646442ab61703fcc02158046trawick * @submodule dom-screen
3f4d7fdb598d64d80ab8656852276246f2f3b502rbb * Returns an Object literal containing the following about this element: (top, right, bottom, left)
a7318397b355119d990d1f311b951dea2aafc53arbb * @method region
a7318397b355119d990d1f311b951dea2aafc53arbb * @param {HTMLElement} element The DOM element.
a7318397b355119d990d1f311b951dea2aafc53arbb @return {Object} Object literal containing the following about this element: (top, right, bottom, left)
fd709745f1226d683c57ad9bbcdd05971d214d0cstoddard * Find the intersect information for the passes nodes.
fd709745f1226d683c57ad9bbcdd05971d214d0cstoddard * @method intersect
fd709745f1226d683c57ad9bbcdd05971d214d0cstoddard * @param {HTMLElement} element The first element
fd709745f1226d683c57ad9bbcdd05971d214d0cstoddard * @param {HTMLElement | Object} element2 The element or region to check the interect with
fd709745f1226d683c57ad9bbcdd05971d214d0cstoddard * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance i.e. DragDrop)
fd709745f1226d683c57ad9bbcdd05971d214d0cstoddard @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
fd709745f1226d683c57ad9bbcdd05971d214d0cstoddard var r = altRegion || DOM.region(node), region = {};
55069cedbbaf2768c1f317c80129c6f869890fb9rbb return false;
b9d75184a83c325dc6cdf5488b0b1a4adec27506stoddard area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
2a7df37e1fa5276b519eb1f04827b96204ba8873trawick inRegion: DOM.inRegion(node, node2, false, altRegion)
864c5615d55b8ebbde24e72043f6325741335a74fielding * Check if any part of this node is in the passed region
864c5615d55b8ebbde24e72043f6325741335a74fielding * @method inRegion
ff33056d9ea71f35e6fb3c17d53a18931be70a99minfrin * @param {Object} node2 The node to get the region from or an Object literal of the region
ff33056d9ea71f35e6fb3c17d53a18931be70a99minfrin * $param {Boolean} all Should all of the node be inside the region
ff33056d9ea71f35e6fb3c17d53a18931be70a99minfrin * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
ff33056d9ea71f35e6fb3c17d53a18931be70a99minfrin * @return {Boolean} True if in region, false if not.
cb5d3f2f217d457dada4883addb1dc9f3f17bb85fielding return false;
0c7d8ecf301c2a3f99deff385bdda0c21ac60af5stoddard if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
0c7d8ecf301c2a3f99deff385bdda0c21ac60af5stoddard return true;
0c7d8ecf301c2a3f99deff385bdda0c21ac60af5stoddard return false;
aa616c3b5a4aa59867472cddf7d8e63693808f0erederpj * Check if any part of this element is in the viewport
aa616c3b5a4aa59867472cddf7d8e63693808f0erederpj * @method inViewportRegion
aa616c3b5a4aa59867472cddf7d8e63693808f0erederpj * @param {HTMLElement} element The DOM element.
80e9324586de2fa55e2da4df409e6a85885ea659fielding * @param {Boolean} all Should all of the node be inside the region
80e9324586de2fa55e2da4df409e6a85885ea659fielding * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
80e9324586de2fa55e2da4df409e6a85885ea659fielding * @return {Boolean} True if in region, false if not.
4682cf97ee2eca42a7222e0113ebacf5ef70c4efrbb return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
9f7fc4627b7d98f6f6955ad6cf0cec5a3e1c4debfielding * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left)
1702068419e130e99f021228659597c1ec658edcchuck * @method viewportRegion
1702068419e130e99f021228659597c1ec658edcchuck @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left)
01f61931c658183042469eb02fd3f61e4e643a6atrawick var r = {};
01f61931c658183042469eb02fd3f61e4e643a6atrawick r[RIGHT] = DOM.winWidth(node) + DOM.docScrollX(node);
7ae8bc63caa2292341a22235223ff1ed17ac02aestoddard r[BOTTOM] = (DOM.docScrollY(node) + DOM.winHeight(node));
23851fdc3ee2eac45ebb85f400a5d719656dfa22rbb * Add style management functionality to DOM.
23851fdc3ee2eac45ebb85f400a5d719656dfa22rbb * @module dom
23851fdc3ee2eac45ebb85f400a5d719656dfa22rbb * @submodule dom-style
23851fdc3ee2eac45ebb85f400a5d719656dfa22rbb * @for DOM
b90c64e517df3fe1c97806830f84a30362187f0afielding// use alpha filter for IE opacity
b90c64e517df3fe1c97806830f84a30362187f0afieldingif (document[DOCUMENT_ELEMENT][STYLE][OPACITY] === UNDEFINED &&
c4be1ca9db22140f3788166f0195304e2fe4743bgregames try { // will error if no DXImageTransform
c4be1ca9db22140f3788166f0195304e2fe4743bgregames val = node[FILTERS]['DXImageTransform.Microsoft.Alpha'][OPACITY];
8019a211b7453e80e6e22db6d41fe68dd7f8c4b8fielding } catch(e) {
8019a211b7453e80e6e22db6d41fe68dd7f8c4b8fielding try { // make sure its in the document
a3a9ceac1bc30598c594c89e1382609496b7752brbb if (typeof style[FILTER] == 'string') { // in case not appended
a3a9ceac1bc30598c594c89e1382609496b7752brbb style[FILTER] = 'alpha(' + OPACITY + '=' + val * 100 + ')';
a3a9ceac1bc30598c594c89e1382609496b7752brbb if (!node[CURRENT_STYLE] || !node[CURRENT_STYLE][HAS_LAYOUT]) {
25e17566bc9005778707317c8919c610513a4418stoddard// IE getComputedStyle
25e17566bc9005778707317c8919c610513a4418stoddard// TODO: unit-less lineHeight (e.g. 1.22)
44ea927aaaa7c419de1c824beb01b26216f387c3dougm re_unit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i;
73579c435f9f6c2670c4391114368a2eedaf8ebfrbb } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert
73579c435f9f6c2670c4391114368a2eedaf8ebfrbb } else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
bf6fc76bb2af745a68396e793d5d51a135a35f54rederpj var current = el[CURRENT_STYLE][prop], // value of "width", "top", etc.
bf6fc76bb2af745a68396e793d5d51a135a35f54rederpj capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc.
bf6fc76bb2af745a68396e793d5d51a135a35f54rederpj offset = 'offset' + capped, // "offsetWidth", "offsetTop", etc.
bf6fc76bb2af745a68396e793d5d51a135a35f54rederpj pixel = 'pixel' + capped, // "pixelWidth", "pixelTop", etc.
4f110a6b1eb8b6a88a2a0c804cf699062f67f708rbb if (actual === UNDEFINED) { // likely "right" or "bottom"
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding // the difference is padding + border (works in Standards & Quirks modes)
66f62d70d05d9011c6ac59d5cd10a24e452fa1b3rbb } else { // convert units to px
66f62d70d05d9011c6ac59d5cd10a24e452fa1b3rbb if (!el[STYLE][pixel] && !el[STYLE][prop]) { // need to map style.width to currentStyle (no currentStyle.pixelWidth)
9832ee60b23ca2a3faa403bbe88720815969a9fefielding el[STYLE][prop] = current; // no style.pixelWidth if no style.width
ee25ccdf4aa79a7a7f2dfc13fc118f0a343422fcwrowe // clientHeight/Width = paddingBox (e.g. offsetWidth - borderWidth)
ee25ccdf4aa79a7a7f2dfc13fc118f0a343422fcwrowe // clientTop/Left = borderWidth
90a8cab05f4d949dd1317df7e19a2f787c46a5f6rbb var value = null;
90a8cab05f4d949dd1317df7e19a2f787c46a5f6rbb if (!el[CURRENT_STYLE][HAS_LAYOUT]) { // TODO: unset layout?
da3e32612f06d3082e41ba709919c996c89b8c06rederpj value = el.offsetHeight - el.clientHeight - el[CLIENT_TOP];
da3e32612f06d3082e41ba709919c996c89b8c06rederpj value = el.offsetWidth - el.clientWidth - el[CLIENT_LEFT];
ae416a3cdff7a12665838a2184183299dcee6ec9bjh // use pixelRight to convert to px
ae416a3cdff7a12665838a2184183299dcee6ec9bjh var val = null,
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx while ( (current = node[CURRENT_STYLE]) && current[att] == 'inherit') { // NOTE: assignment in test
73cd9876e07c696a3e3563277a1d4e3173861af6stoddard Y.DOM.elementByAxis(node, PARENT_NODE, null, function(parent) {
2281907b9a2a509aa0eabdc0b1d21424018dbbdfrbb return true;
893328ef6ff86d0ca27774778d84410353789fb0fielding//fontSize: getPixelFont,
893328ef6ff86d0ca27774778d84410353789fb0fielding// TODO: top, right, bottom, left
274de94b0b59f4ee126dca1726624980828d0cd0stoddardIEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset;
274de94b0b59f4ee126dca1726624980828d0cd0stoddardIEComputed.color = IEComputed.backgroundColor = ComputedStyle.getColor;
85d733e70c94a57c9ff893ed05d8b9cfcd0f083fstoddardIEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] =
85d733e70c94a57c9ff893ed05d8b9cfcd0f083fstoddard IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] =
3f0dd56fa6b79fe389f20738369b290e2f3e9201trawickIEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom =
70b83609159f247f5920421a890dc27a0718d63adreid IEComputed.borderRightColor = IEComputed.borderBottomColor =
70b83609159f247f5920421a890dc27a0718d63adreid IEComputed.borderLeftColor = ComputedStyle.getBorderColor;
bd2d582e0f0708b6e8e258a9a5f9a15445752087trawick * Provides helper methods for collecting and filtering DOM elements.
adb8ad10ffc20ed06ec6cfab6cd7933ab429ea7dtrawick * @module dom
adb8ad10ffc20ed06ec6cfab6cd7933ab429ea7dtrawick * @submodule selector
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbb * Provides helper methods for collecting and filtering DOM elements.
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbb * @class Selector
157e6980a24a44e4719173b1c555133caecbc172stoddardvar reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;
171f8c636ff1374e3a3dfff333211becda355b98trawick attributes: /^\[([a-z]+\w*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i,
171f8c636ff1374e3a3dfff333211becda355b98trawick combinator: /^\s*([>+~]|\s)\s*/
faa6e5d8b210456ae4dad0398dfa40a19fd89d59coarvar Selector = {
faa6e5d8b210456ae4dad0398dfa40a19fd89d59coar * Default document for use queries
faa6e5d8b210456ae4dad0398dfa40a19fd89d59coar * @property document
ed105ee460bbaf479f0aa0f59d3951da85066e27stoddard * @type object
ed105ee460bbaf479f0aa0f59d3951da85066e27stoddard * @default window.document
ed105ee460bbaf479f0aa0f59d3951da85066e27stoddard document: Y.config.doc,
ed105ee460bbaf479f0aa0f59d3951da85066e27stoddard * Mapping of attributes to aliases, normally to work around HTMLAttributes
ed105ee460bbaf479f0aa0f59d3951da85066e27stoddard * that conflict with JS reserved words.
ed105ee460bbaf479f0aa0f59d3951da85066e27stoddard * @property attrAliases
ed105ee460bbaf479f0aa0f59d3951da85066e27stoddard * @type object
bae64a3e5bf7b96d8379e24f13273f26b3b29e16coar attrAliases: {},
c7fe488773cf6f50a1b2d9211c2f30a2ace8b67ccoar * Mapping of shorthand tokens to corresponding attribute selector
c7fe488773cf6f50a1b2d9211c2f30a2ace8b67ccoar * @property shorthand
c7fe488773cf6f50a1b2d9211c2f30a2ace8b67ccoar * @type object
27338fc39af80f2f0e4a8dbdc90c8a8179a5b2e4rbb shorthand: {
853a0c44563b056e40e9cffe911190f554e63ec3chuck * List of operators and corresponding boolean functions.
853a0c44563b056e40e9cffe911190f554e63ec3chuck * These functions are passed the attribute and the current node's value of the attribute.
f1fa5e69040a3a72054d185f6087a7d1592b83e8rbb '=': function(attr, val) { return attr === val; }, // Equality
f1fa5e69040a3a72054d185f6087a7d1592b83e8rbb '!=': function(attr, val) { return attr !== val; }, // Inequality
f1fa5e69040a3a72054d185f6087a7d1592b83e8rbb '~=': function(attr, val) { // Match one of space seperated words
f1fa5e69040a3a72054d185f6087a7d1592b83e8rbb var s = ' ';
30e3e9b782c701f885583b7d13d8e46c37d7e1ddtrawick '|=': function(attr, val) { return Y.DOM._getRegExp('^' + val + '[-]?').test(attr); }, // Match start with value followed by optional hyphen
30e3e9b782c701f885583b7d13d8e46c37d7e1ddtrawick '^=': function(attr, val) { return attr.indexOf(val) === 0; }, // Match starts with value
30e3e9b782c701f885583b7d13d8e46c37d7e1ddtrawick '$=': function(attr, val) { return attr.lastIndexOf(val) === attr[LENGTH] - val[LENGTH]; }, // Match ends with value
27faa3af8a50c1dc2dc6cb3049722378f85e5517rbb '*=': function(attr, val) { return attr.indexOf(val) > -1; }, // Match contains value as substring
27faa3af8a50c1dc2dc6cb3049722378f85e5517rbb '': function(attr, val) { return attr; } // Just test for existence of attribute
141b1a93f508248cbc0e9a124cc38041eb3e2562rbb * List of pseudo-classes and corresponding boolean functions.
141b1a93f508248cbc0e9a124cc38041eb3e2562rbb * These functions are called with the current node, and any value that was parsed with the pseudo regex.
141b1a93f508248cbc0e9a124cc38041eb3e2562rbb * @property pseudos
141b1a93f508248cbc0e9a124cc38041eb3e2562rbb * @type object
6501b757f710f75d47c950300d8110aca67dc0b0rbb return Selector.getNth(node, val, node[TAG_NAME], true);
c9a95767fbf0f5fb0976a06b97a256033925e433rbb return Y.DOM.firstChildByTag(node[PARENT_NODE], node[TAG_NAME]) === node;
d8d839738b1e80b0f9c54e83677b3f2c46c22705rbb return Y.DOM.lastChildByTag(node[PARENT_NODE], node[TAG_NAME]) === node;
d8d839738b1e80b0f9c54e83677b3f2c46c22705rbb return Y.DOM.childrenByTag(node[PARENT_NODE], node[TAG_NAME])[LENGTH] === 1;
2e970b7ec485dde18f8fb3f494f98a3f68749859fanf * Test if the supplied node matches the supplied selector.
a5a7ecb732cfe89bb1f8e3c61b316c2075cefe52rbb * @method test
a5a7ecb732cfe89bb1f8e3c61b316c2075cefe52rbb * @param {HTMLElement | String} node An id or node reference to the HTMLElement being tested.
364701a102725758f2e3a511924381e2faa93e27rbb * @param {string} selector The CSS Selector to test the node against.
364701a102725758f2e3a511924381e2faa93e27rbb * @return{boolean} Whether or not the node matches the selector.
0811e8a41d152f0016a385ce1dfa44f475425b70rbb return false;
957b9b3f5e47c6cc7c2d8d9e2224c7364e966c70rbb if ( Selector._testNode(node, groups[i]) ) { // passes if ANY group matches
957b9b3f5e47c6cc7c2d8d9e2224c7364e966c70rbb return true;
e91c80d53d8ffa738283d923638fa3efd8aa6bf7rbb return false;
d0211374a981173d4537e3f919c708b5f64040fcgstein * Filters a set of nodes based on a given CSS selector.
d0211374a981173d4537e3f919c708b5f64040fcgstein * @method filter
37d15e1062df9dcdd39ebee5bd2fdc75d4a6aa4arbb * @param {array} nodes A set of nodes/ids to filter.
37d15e1062df9dcdd39ebee5bd2fdc75d4a6aa4arbb * @param {string} selector The selector used to test each node.
e3ec3193b69b45923c14915fa3ee3bc1f0215bafrbb * @return{array} An array of nodes from the supplied array that match the given selector.
138c8f7cb8254e035c6f45288e3909cd9c21be5cmartin var result = Selector._filter(nodes, Selector._tokenize(selector)[0]);
adaea88da2d103e4302e361c932b98cee86fb1c5rbb * Retrieves a set of nodes based on a given CSS selector.
adaea88da2d103e4302e361c932b98cee86fb1c5rbb * @method query
8a76b3f3c93d39930182afa227d258218f80926brbb * @param {string} selector The CSS Selector to test the node against.
8e7c85d6eb9bf628f081763c5bd778b784d5001crbb * @param {HTMLElement | String} root optional An id or HTMLElement to start the query from. Defaults to Selector.document.
8e7c85d6eb9bf628f081763c5bd778b784d5001crbb * @param {Boolean} firstOnly optional Whether or not to return only the first match.
8e7c85d6eb9bf628f081763c5bd778b784d5001crbb * @return {Array} An array of nodes that match the given selector.
97ad13ce0413b573e63512b57c874ebbd41065b2rbb var result = Selector._query(selector, root, firstOnly);
c5c3b5e33fca6425dc716e1dc51c10733d9b6bc3rbb var groups = selector.split(','); // TODO: handle comma in attribute/pseudo
be7b08f10dc6b0be088c8b41009d89ea49ad4acarbb found = arguments.callee(groups[i], root, firstOnly, true);
8a76b3f3c93d39930182afa227d258218f80926brbb var idToken = tokens[Selector._getIdTokenIndex(tokens)],
1a3161b56ebbbd036730d5372d4800cc495db212rbb // use id shortcut when possible
2d87d8f191175a0683f430d790d81a5604b74ec6rbb if (node && (root[NODE_TYPE] === 9 || Y.DOM.contains(root, node))) {
84b76faff9e8fa4b16b587b95d3930e36fe3c405rbb result = Selector._filter(nodes, token, firstOnly, deDupe);
bcef91d7068817e2e56854f5c5b22b6eb4663a85rbb return false;
445997e06464e7625c7f0e22917f8f2d9876cfffrbb return false;
a2c240fe8836beba2330b03d55569d9e31bb3358trawick Selector._foundCache[Selector._foundCache[LENGTH]] = node;
a2c240fe8836beba2330b03d55569d9e31bb3358trawick return true;
5a58a10705b7b154b53294e0c0283d64eabdcb7fstoddard _testNode: function(node, selector, token, deDupe) {
5a58a10705b7b154b53294e0c0283d64eabdcb7fstoddard token = token || Selector._tokenize(selector).pop() || {};
98f3c8c547839251cb43e9f917114cc8b16ced9efanf (token[TAG] !== '*' && node[TAG_NAME].toUpperCase() !== token[TAG]) ||
1a411968bb62cc88c3cbf14a53caf6587c224259fanf return false;
10a2de5cee9ae5abe675ea200fbe635a54556c8ffanf for (i = 0, len = token[ATTRIBUTES][LENGTH]; i < len; ++i) {
60777c94cb33363389d4848524c0809c235ba5e5rbb attribute = node.getAttribute(token[ATTRIBUTES][i][0], 2);
b5140df3124b186e4a977812fd9828d1e295c080wrowe return false;
b5140df3124b186e4a977812fd9828d1e295c080wrowe !ops[token[ATTRIBUTES][i][1]](attribute, token[ATTRIBUTES][i][2])) {
b5140df3124b186e4a977812fd9828d1e295c080wrowe return false;
41aef8943f349ee0b5b510dd436301b4c33c628cwrowe for (i = 0, len = token[PSEUDOS][LENGTH]; i < len; ++i) {
bb360f1d9bdce4f55f290de07a711db006b25957wrowe !pseudos[token[PSEUDOS][i][0]](node, token[PSEUDOS][i][1])) {
5727f68f33838686d447f55a100309e54efb20f8fielding return false;
b974a8fc59a9d6193305dcd8690992a411d88232rbb _clearFoundCache: function() {
b974a8fc59a9d6193305dcd8690992a411d88232rbb for (var i = 0, len = Selector._foundCache[LENGTH]; i < len; ++i) {
fa996ff928f6170678c8789c8073c368f56d770arbb try { // IE no like delete
fa996ff928f6170678c8789c8073c368f56d770arbb } catch(e) {
b31025f6f2c0392dc76eecca7f27faad0b902be0wrowe return true;
4783bc116b4dc37deadcc0b68ce3d3eeb6a7464aben return false;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb return Selector._testNode(node[PARENT_NODE], null, token.previous);
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if (sib && Selector._testNode(sib, null, token.previous)) {
cab10c98980b42562a7850410cecd37798e170ecrbb return true;
cab10c98980b42562a7850410cecd37798e170ecrbb return false;
2714d6002fcdf12f5b26cc948c9f2f03ca5e7ee9rbb if (sib[NODE_TYPE] === 1 && Selector._testNode(sib, null, token.previous)) {
2714d6002fcdf12f5b26cc948c9f2f03ca5e7ee9rbb return true;
8695c28e4d0bb9357f606045b37238d4f49ce8b6rbb return false;
5f69f46ccdf50afd8f0a23f134746e6066185e89rbb an+b = get every _a_th node starting at the _b_th
5f69f46ccdf50afd8f0a23f134746e6066185e89rbb 0n+b = no repeat ("0" and "n" may both be omitted (together) , e.g. "0n+1" or "1", not "0+1"), return only the _b_th element
5f69f46ccdf50afd8f0a23f134746e6066185e89rbb 1n+b = get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
5f69f46ccdf50afd8f0a23f134746e6066185e89rbb an+0 = get every _a_th element, "0" may be omitted
e76797ee89ad6fb15ad97b0f3903ae324ac44949wrowe var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
e76797ee89ad6fb15ad97b0f3903ae324ac44949wrowe b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
2c8f06bf370a44a3d0544ed5319355463c417132gregames } else if ( isNaN(a) ) {
2c8f06bf370a44a3d0544ed5319355463c417132gregames a = (n) ? 1 : 0; // start from the first or no repeat
8ba9d5e9aaaa79dba0de13f5c1b6e725d98f1dc2fanf return true;
26cf4d32b4ff8807a64b0cfa6865a7d6d171c68efanf return false;
06c107289de0a0888386e0bc08ef9fc60aacd8bctrawick } else if (a < 0) {
06c107289de0a0888386e0bc08ef9fc60aacd8bctrawick a = Math.abs(a);
b0bd38b2226e5cfb86cce6ed1991723f4c9e4f68trawick for (i = b - 1, len = siblings[LENGTH]; i < len; i += a) {
bf9902ea6090f94c9ee0aaddd80b419a184ffe55jim return true;
bf9902ea6090f94c9ee0aaddd80b419a184ffe55jim for (i = siblings[LENGTH] - b, len = siblings[LENGTH]; i >= 0; i -= a) {
0b34df54ff22d0ca05eb8e9d7c9610138a878c83rbb return true;
0b34df54ff22d0ca05eb8e9d7c9610138a878c83rbb return false;
0ea568e49752d337d2b513cce07f2a6f4699d6eatrawick for (var i = 0, len = tokens[LENGTH]; i < len; ++i) {
328d02603f471fad56cc5588fc9e93f589593ad0rbb return -1;
48a2f5e2c189669b025d462f44fda5d4b45e8d78trawick Break selector into token units per simple selector.
48a2f5e2c189669b025d462f44fda5d4b45e8d78trawick Combinator is attached to left-hand selector.
48a2f5e2c189669b025d462f44fda5d4b45e8d78trawick var token = {}, // one token per simple selector (left selector holds combinator)
48a2f5e2c189669b025d462f44fda5d4b45e8d78trawick found = false, // whether or not any matches were found this pass
b22fb75c37b70fbe176afdb8081c3ce2dba86db4rbb selector = Selector._replaceShorthand(selector); // convert ID and CLASS shortcuts to attributes
8fccb89ed59d5c80c76a818f7ca02bb0d068d4d3rbb Search for selector patterns, store, and strip them from the selector string
8fccb89ed59d5c80c76a818f7ca02bb0d068d4d3rbb until no patterns match (invalid selector) or we run out of chars.
8fccb89ed59d5c80c76a818f7ca02bb0d068d4d3rbb Multiple attributes and pseudos are allowed, in any order.
8fccb89ed59d5c80c76a818f7ca02bb0d068d4d3rbb for example:
da07a882b90b44243c9cd88ac09a789999dccc4drbb 'form:first-child[type=button]:not(button)[lang|=en]'
4a5c8a77f48f0cf10bfe70479d0a2e8e7d6cd917rbb if (re != TAG && re != COMBINATOR) { // only one allowed
4a5c8a77f48f0cf10bfe70479d0a2e8e7d6cd917rbb if ((match = patterns[re].exec(selector))) { // note assignment
5bf029f8452b6aa105cf3d9d9b19221920725428rbb if (re != TAG && re != COMBINATOR) { // only one allowed
5bf029f8452b6aa105cf3d9d9b19221920725428rbb //token[re] = token[re] || [];
60ed053fe71b1e3cfab8c4ed37afde30a6db4841rbb // capture ID for fast path to element
e03878add0099ba9741efc46d545955a60ea8bdcrbb } else { // single selector (tag, combinator)
1860b2b5f1de31f8cf9d95f1b394fe98c8dbfab7rbb selector = selector.replace(match[0], ''); // strip current match from selector
9ec65cbae2f760e485a1c54df5b19853688d5c91wrowe if (re === COMBINATOR || !selector[LENGTH]) { // next token or done
9ec65cbae2f760e485a1c54df5b19853688d5c91wrowe token[ATTRIBUTES] = Selector._fixAttributes(token[ATTRIBUTES]);
9ec65cbae2f760e485a1c54df5b19853688d5c91wrowe token[TAG] = token[TAG] ? token[TAG].toUpperCase() : '*';
886cd69ebf69e990dbc365be87ff8ea7cd681904rbb if (aliases[attr[i][0]]) { // convert reserved words, etc
e1ade9256c87684358786fcf7eef251bd4c1db10rbb var attrs = selector.match(patterns[ATTRIBUTES]); // pull attributes to avoid false pos on "." and "#"
e1ade9256c87684358786fcf7eef251bd4c1db10rbb selector = selector.replace(patterns[ATTRIBUTES], 'REPLACED_ATTRIBUTE');
db9ac238bf63d7df2bebbaff4de1628a32151028trawick selector = selector.replace(Y.DOM._getRegExp(re, 'gi'), shorthand[re]);
42ec91fadb5532438ab4c02993b15c18a517967frbb selector = selector.replace('REPLACED_ATTRIBUTE', attrs[i]);
2975523a2901fc601ae9510082a7d4fb11bb9aecakeif (Y.UA.ie && Y.UA.ie < 8) { // rewrite class for IE (others use getAttribute('class')
e7270e4daeb3e62414b361ca2bf0e707d0ae3310wrowe * Add style management functionality to DOM.
e7270e4daeb3e62414b361ca2bf0e707d0ae3310wrowe * @module dom
e7270e4daeb3e62414b361ca2bf0e707d0ae3310wrowe * @submodule dom-style
cfa64348224b66dd1c9979b809406c4d15b1c137fielding re_RGB: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
cfa64348224b66dd1c9979b809406c4d15b1c137fielding re_hex: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
cfa64348224b66dd1c9979b809406c4d15b1c137fielding var r = (RE.$1.length === 1) ? '0' + RE.$1 : Number(RE.$1),
cfa64348224b66dd1c9979b809406c4d15b1c137fielding g = (RE.$2.length === 1) ? '0' + RE.$2 : Number(RE.$2),
cfa64348224b66dd1c9979b809406c4d15b1c137fielding b = (RE.$3.length === 1) ? '0' + RE.$3 : Number(RE.$3);
cfa64348224b66dd1c9979b809406c4d15b1c137fielding if (val !== 'transparent' && val.indexOf('#') < 0) {
cfa64348224b66dd1c9979b809406c4d15b1c137fielding}, '@VERSION@' );