dom.js revision 81ba27a21e393896f8d167f996e7d8af8221e307
* Provides DOM helper methods. * Returns the HTMLElement with the given ID (Wrapper for document.getElementById). * @param {String} id the id attribute * @param {Object} doc optional The document to search. Defaults to current document * @return {HTMLElement | null} The HTMLElement with the id, or null if none found. * Returns the text content of the HTMLElement. * @param {HTMLElement} element The html element. * @return {String} The text content of the element (includes text of any descending elements). * Sets the text content of the HTMLElement. * @param {HTMLElement} element The html element. * @param {String} content The content to add. * Finds the previous sibling of the element. * @deprecated Use elementByAxis * @param {HTMLElement} element The html element. * @param {Function} fn optional An optional boolean test to apply. * The optional function is passed the current DOM node being tested as its only argument. * If no function is given, the first sibling is returned. * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes. * @return {HTMLElement | null} The matching DOM node or null if none found. * Finds the next sibling of the element. * @deprecated Use elementByAxis * @param {HTMLElement} element The html element. * @param {Function} fn optional An optional boolean test to apply. * The optional function is passed the current DOM node being tested as its only argument. * If no function is given, the first sibling is returned. * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes. * @return {HTMLElement | null} The matching DOM node or null if none found. * Finds the ancestor of the element. * @deprecated Use elementByAxis * @param {HTMLElement} element The html element. * @param {Function} fn optional An optional boolean test to apply. * The optional function is passed the current DOM node being tested as its only argument. * If no function is given, the parentNode is returned. * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes. * @return {HTMLElement | null} The matching DOM node or null if none found. // TODO: optional stopAt node? * Searches the element by the given axis for the first matching element. * @param {HTMLElement} element The html element. * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling). * @param {Function} fn optional An optional boolean test to apply. * @param {Boolean} all optional Whether all node types should be returned, or just element nodes. * The optional function is passed the current HTMLElement being tested as its only argument. * If no function is given, the first element is returned. * @return {HTMLElement | null} The matching element or null if none found. * Determines whether or not one HTMLElement is or contains another HTMLElement. * @param {HTMLElement} element The containing html element. * @param {HTMLElement} needle The html element that may be contained. * @return {Boolean} Whether or not the element is or contains the needle. * Determines whether or not the HTMLElement is part of the document. * @param {HTMLElement} element The containing html element. * @param {HTMLElement} doc optional The document to check. * @return {Boolean} Whether or not the element is attached to the document. if (!
id) {
// TODO: remove when done? * Creates a new dom node using the provided markup string. * @param {String} html The markup used to create the element * @param {HTMLDocument} doc An optional document context if (
typeof html ===
'string') {
if (
typeof custom[m[
1]] ===
'function') {
if (
nodes.
length ===
1) {
// return single node, breaking parentNode ref from "fragment" }
else {
// return multiple nodes as a fragment if (
nodes.
item) {
// convert live list to static array }
// else inline with log for minification * Provides a normalized attribute interface. * @param {String | HTMLElement} el The target element for the attribute. * @param {String} attr The attribute to set. * @param {String} val The value of the attribute. * Provides a normalized attribute interface. * @param {String | HTMLElement} el The target element for the attribute. * @param {String} attr The attribute to get. * @return {String} The current value of the attribute. ret =
'';
// per DOM spec * Inserts content in a node at the given location * @param {HTMLElement} node The node to insert into * @param {String} content The content to be inserted * @param {String} where Where to insert the content; default is after lastChild }
else {
// create from string and cache if (
where.
nodeType) {
// insert regardless of relationship to node // TODO: check if node.contains(where)? var ret =
'',
// TODO: return null? return (
typeof ret ===
'string') ?
ret :
'';
* Brute force version of contains. * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc). * @param {HTMLElement} element The containing html element. * @param {HTMLElement} needle The html element that may be contained. * @return {Boolean} Whether or not the element is or contains the needle. * Memoizes dynamic regular expressions to boost runtime performance. * @param {String} str The string to convert to a regular expression. * @param {String} flags optional An optinal string of flags. * @return {RegExp} An instance of RegExp * returns the appropriate document. * @param {HTMLElement} element optional Target element. * @return {Object} The document for the given element or the default document. * returns the appropriate window. * @param {HTMLElement} element optional Target element. * @return {Object} The window for the given element or the default window. // IE adds TBODY when creating TABLE elements (which may share this impl) // IE: node.value changes the button text, which should be handled via innerHTML * Determines whether a DOM element has the given className. * @param {HTMLElement} element The DOM element. * @param {String} className the class name to search for * @return {Boolean} Whether or not the element has the given class. * Adds a class name to a given DOM element. * @param {HTMLElement} element The DOM element. * @param {String} className the class name to add to the class attribute * Removes a class name from a given element. * @param {HTMLElement} element The DOM element. * @param {String} className the class name to remove from the class attribute * Replace a class with another class for a given element. * If no oldClassName is present, the newClassName is simply added. * @param {HTMLElement} element The DOM element. * @param {String} oldClassName the class name to be replaced * @param {String} newClassName the class name that will be replacing the old class name * If the className exists on the node it is removed, if it doesn't exist it is added. * @param {HTMLElement} element The DOM element. * @param {String} className the class name to be toggled YUI.
add(
'dom-style',
function(Y) {
* Add style management functionality to DOM. * Sets a style property for a given element. * @param {HTMLElement} An HTMLElement to apply the style to. * @param {String} att The style property to set. * @param {String|Number} val The value. val =
'';
// normalize for unsetting * Returns the current style value for the given property. * @param {HTMLElement} An HTMLElement to get the style from. * @param {String} att The style property to get. if (
val ===
'') {
// TODO: is empty string sufficient? * Sets multiple style properties. * @param {HTMLElement} node An HTMLElement to apply the styles to. * @param {Object} hash An object literal of property:value pairs. * Returns the computed style for the given node. * @method getComputedStyle * @param {HTMLElement} An HTMLElement to get the style from. * @param {String} att The style property to get. * @return {String} The computed value of the style property. // normalize reserved word float alternatives ("cssFloat" or "styleFloat") // fix opera computedStyle default color unit (convert to rgb) // safari converts transparent to rgba(), others use "transparent" if (
val ===
'rgba(0, 0, 0, 0)') {
re_RGB: /^
rgb\(([
0-
9]+)\s*,\s*([
0-
9]+)\s*,\s*([
0-
9]+)\)$/i,
re_hex: /^#?([
0-
9A-F]{
2})([
0-
9A-F]{
2})([
0-
9A-F]{
2})$/i,
// TODO: unit-less lineHeight (e.g. 1.22) width: [
'Left',
'Right'],
offset =
'offset' +
capped,
// "offsetWidth", "offsetTop", etc. pixel =
'pixel' +
capped,
// "pixelWidth", "pixelTop", etc. // IE pixelWidth incorrect for percent // manually compute by subtracting padding and border from offset size // NOTE: clientWidth/Height (size minus border) is 0 when current === AUTO so offsetHeight is used // reverting to auto from auto causes position stacking issues (old impl) }
else {
// use style.pixelWidth, etc. to convert to pixels // need to map style.width to currentStyle (no currentStyle.pixelWidth) // use pixelRight to convert to px //fontSize: getPixelFont, // use alpha filter for IE opacity try {
// will error if no DXImageTransform try {
// make sure its in the document if (
val ===
'') {
// normalize inline style behavior if (
typeof style[
FILTER] ==
'string') {
// in case not appended }
catch(e) {
// IE throws error on invalid style set; trap common cases// TODO: top, right, bottom, left },
'@VERSION@' ,{
requires:[
'dom-base']});
YUI.
add(
'dom-screen',
function(Y) {
* Adds position and region management functionality to DOM. // TODO: does caption matter? * Returns the inner height of the viewport (exludes scrollbar). * @return {Number} The current height of the viewport. * Returns the inner width of the viewport (exludes scrollbar). * @return {Number} The current width of the viewport. * @return {Number} The current height of the document. * @return {Number} The current width of the document. * Amount page has been scroll horizontally * @return {Number} The current amount the screen is scrolled horizontally. * Amount page has been scroll vertically * @return {Number} The current amount the screen is scrolled vertically. * Gets the current position of an element based on page coordinates. * Element must be part of the DOM tree to have page coordinates * (display:none or elements not appended return false). * @param element The target element * @return {Array} The XY position of the element }
else {
// default to current offsets return function(
node) {
// manually calculate by crawling up offsetParents //Calculate the Top and Left border sizes (assumes pixels) // TODO: refactor with !! or just falsey // TODO: worth refactoring for TOP/LEFT only? // account for any scrolled ancestors //Firefox does something funky with borders when overflow is not visible. //Fix FIXED position -- add scrollbars }(),
// NOTE: Executing for loadtime branching if (
isNaN(
xy[
0]) ) {
// in case of 'auto' if (
isNaN(
xy[
0]) ) {
// default to offset value if (
isNaN(
xy[
1]) ) {
// in case of 'auto' if (
isNaN(
xy[
1]) ) {
// default to offset value * Gets the current X position of an element based on page coordinates. * Element must be part of the DOM tree to have page coordinates * (display:none or elements not appended return false). * @param element The target element * @return {Int} The X position of the element * Gets the current Y position of an element based on page coordinates. * Element must be part of the DOM tree to have page coordinates * (display:none or elements not appended return false). * @param element The target element * @return {Int} The Y position of the element * Set the position of an html element in page coordinates. * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). * @param element The target element * @param {Array} xy Contains X & Y values for new position (coordinates are page-based) * @param {Boolean} noRetry By default we try and set the position a second time if the first fails if (
pos ==
'static') {
// default to relative * Set the X position of an html element in page coordinates, regardless of how the element is positioned. * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). * @param element The target element * @param {Int} x The X values for new position (coordinates are page-based) * Set the Y position of an html element in page coordinates, regardless of how the element is positioned. * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). * @param element The target element * @param {Int} y The Y values for new position (coordinates are page-based) if (
mode !=
'CSS1Compat') {
// Quirks * Returns an Object literal containing the following about this element: (top, right, bottom, left) * @param {HTMLElement} element The DOM element. @return {Object} Object literal containing the following about this element: (top, right, bottom, left) * Find the intersect information for the passes nodes. * @param {HTMLElement} element The first element * @param {HTMLElement | Object} element2 The element or region to check the interect with * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance i.e. DragDrop) @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion) * Check if any part of this node is in the passed region * @param {Object} node2 The node to get the region from or an Object literal of the region * $param {Boolean} all Should all of the node be inside the region * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop) * @return {Boolean} True if in region, false if not. * Check if any part of this element is in the viewport * @method inViewportRegion * @param {HTMLElement} element The DOM element. * @param {Boolean} all Should all of the node be inside the region * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop) * @return {Boolean} True if in region, false if not. * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left) @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left) },
'@VERSION@' ,{
requires:[
'dom-base',
'dom-style']});
YUI.
add(
'selector-native',
function(Y) {
* The selector-native module provides support for native querySelector * @submodule selector-native * Provides support for using CSS selectors to query the DOM Y.
namespace(
'Selector');
// allow native module to standalone * Retrieves a set of nodes based on a given CSS selector. * @param {string} selector The CSS Selector to test the node against. * @param {HTMLElement} root optional An HTMLElement to start the query from. Defaults to Y.config.doc * @param {Boolean} firstOnly optional Whether or not to return only the first match. * @return {Array} An array of nodes that match the given selector. // split group into seperate queries if (!
firstOnly) {
// coerce DOM Collection to Array // allows element scoped queries to begin with combinator // e.g. query('> p', document.body) === query('body > p') // enforce for element scoping }
catch(e) {
// fallback to brute if available for (i =
0; (
group =
groups[i++]);) {
// TODO: off-dom test },
'@VERSION@' ,{
requires:[
'dom-base']});
YUI.
add(
'selector-css2',
function(Y) {
* The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements. * @submodule selector-css2 * Provides helper methods for collecting and filtering DOM elements. pseudos: /:([\-\w]+(?:\(?:[
'"]?(.+)['"]?\)))*/i, * Mapping of shorthand tokens to corresponding attribute selector '\\#(-?[_a-z]+[-\\w]*)': '[id=$1]', '\\.(-?[_a-z]+[-\\w]*)': '[className~=$1]' * List of operators and corresponding boolean functions. * These functions are passed the attribute and the current node's value of the attribute. '': function(node, attr) { return Y.DOM.getAttribute(node, attr) !== ''; }, // Just test for existence of attribute //'=': '^{val}$', // equality '~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited '|=': '^{val}-?' // optional hyphen-delimited 'first-child': function(node) { return Y.Selector._children(node[PARENT_NODE])[0] === node; _bruteQuery: function(selector, root, firstOnly) { tokens = Selector._tokenize(selector), token = tokens[tokens.length - 1], rootDoc = Y.DOM._getDoc(root), // if we have an initial ID, set to root when in document if (tokens[0] && rootDoc === root && rootDoc.getElementById(id)) { root = rootDoc.getElementById(id); className = token.className; tagName = token.tagName || '*'; if (rootDoc.getElementById(id)) { // if in document nodes = [rootDoc.getElementById(id)]; // TODO: DOM.byId? // try className if supported nodes = root.getElementsByClassName(className); } else if (tagName) { // default to tagName nodes = root.getElementsByTagName(tagName || '*'); ret = Selector._filterNodes(nodes, tokens, firstOnly); _filterNodes: function(nodes, tokens, firstOnly) { getters = Y.Selector.getters, for (i = 0; (tmpNode = node = nodes[i++]);) { while (tmpNode && tmpNode.tagName) { while ((test = tests[--j])) { value = getters[test[0]](tmpNode, test[0]); value = tmpNode[test[0]]; // use getAttribute for non-standard attributes if (value === undefined && tmpNode.getAttribute) { value = tmpNode.getAttribute(test[0]); if ((operator === '=' && value !== test[2]) || // fast path for equality (operator.test && !operator.test(value)) || // regex test (operator.call && !operator(tmpNode, test[0]))) { // function test // skip non element nodes or non-matching tags if ((tmpNode = tmpNode[path])) { (token.tagName && token.tagName !== tmpNode.tagName)) n--; // move to next token // now that we've passed the test, move up the tree by combinator if (!pass && (combinator = token.combinator)) { // skip non element nodes while (tmpNode && !tmpNode.tagName) { if (combinator.direct) { // one pass only } else { // success if we made it this far }// while (tmpNode = node = nodes[++i]); _getRegExp: function(str, flags) { var regexCache = Selector._regexCache; if (!regexCache[str + flags]) { regexCache[str + flags] = new RegExp(str, flags); return regexCache[str + flags]; re: /^\[([a-z]+\w*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)[
'"]?\]/i, fn: function(match, token) { var operator = match[2] || '', operators = Y.Selector.operators, // add prefiltering for ID and CLASS if ((match[1] === 'id' && operator === '=
') || document.getElementsByClassName && (operator === '~=
' || operator === '=
'))) { token.prefilter = match[1]; token[match[1]] = match[3]; if (operator in operators) { test = operators[operator]; if (typeof test === 'string') { test = Y.Selector._getRegExp(test.replace('{
val}
', match[3])); if (!token.last || token.prefilter !== match[1]) { re: /^((?:-?[_a-z]+[\w-]*)|\*)/i, fn: function(match, token) { var tag = match[1].toUpperCase(); if (tag !== '*
' && (!token.last || token.prefilter)) { return [TAG_NAME, '=
', tag]; fn: function(match, token) { re: /^:([\-\w]+)(?:\(['"]?(.+)['"]?\))*/i,
if (
test) {
// reorder match array }
else {
// selector token not supported (possibly missing CSS3 module) Break selector into token units per simple selector. Combinator is attached to the previous token. tokens = [],
// array of tokens found =
false,
// whether or not any matches were found this pass match,
// the regex match Search for selector patterns, store, and strip them from the selector string until no patterns match (invalid selector) or we run out of chars. Multiple attributes and pseudos are allowed, in any order. 'form:first-child[type=button]:not(button)[lang|=en]' found =
false;
// reset after full pass if (
test ===
false) {
// selector not supported // IE wants class with native queries },
'@VERSION@' ,{
requires:[
'selector-native']});
YUI.
add(
'selector',
function(Y){},
'@VERSION@' ,{
use:[
'selector-native',
'selector-css2']});
YUI.
add(
'dom',
function(Y){},
'@VERSION@' ,{
use:[
'dom-base',
'dom-style',
'dom-screen',
'selector']});