import v1.1.0_beta1 | 2009-08-21
This commit is contained in:
655
webdir/javascript/yui/selector/selector-debug.js
vendored
Normal file
655
webdir/javascript/yui/selector/selector-debug.js
vendored
Normal file
@ -0,0 +1,655 @@
|
||||
/*
|
||||
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
|
||||
Code licensed under the BSD License:
|
||||
http://developer.yahoo.net/yui/license.txt
|
||||
version: 2.7.0
|
||||
*/
|
||||
/**
|
||||
* The selector module provides helper methods allowing CSS3 Selectors to be used with DOM elements.
|
||||
* @module selector
|
||||
* @title Selector Utility
|
||||
* @namespace YAHOO.util
|
||||
* @requires yahoo, dom
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Y = YAHOO.util;
|
||||
|
||||
/**
|
||||
* Provides helper methods for collecting and filtering DOM elements.
|
||||
* @namespace YAHOO.util
|
||||
* @class Selector
|
||||
* @static
|
||||
*/
|
||||
|
||||
Y.Selector = {
|
||||
_foundCache: [],
|
||||
_regexCache: {},
|
||||
|
||||
_re: {
|
||||
nth: /^(?:([-]?\d*)(n){1}|(odd|even)$)*([-+]?\d*)$/,
|
||||
attr: /(\[.*\])/g,
|
||||
urls: /^(?:href|src)/
|
||||
},
|
||||
|
||||
/**
|
||||
* Default document for use queries
|
||||
* @property document
|
||||
* @type object
|
||||
* @default window.document
|
||||
*/
|
||||
document: window.document,
|
||||
/**
|
||||
* Mapping of attributes to aliases, normally to work around HTMLAttributes
|
||||
* that conflict with JS reserved words.
|
||||
* @property attrAliases
|
||||
* @type object
|
||||
*/
|
||||
attrAliases: {
|
||||
},
|
||||
|
||||
/**
|
||||
* Mapping of shorthand tokens to corresponding attribute selector
|
||||
* @property shorthand
|
||||
* @type object
|
||||
*/
|
||||
shorthand: {
|
||||
//'(?:(?:[^\\)\\]\\s*>+~,]+)(?:-?[_a-z]+[-\\w]))+#(-?[_a-z]+[-\\w]*)': '[id=$1]',
|
||||
'\\#(-?[_a-z]+[-\\w]*)': '[id=$1]',
|
||||
'\\.(-?[_a-z]+[-\\w]*)': '[class~=$1]'
|
||||
},
|
||||
|
||||
/**
|
||||
* List of operators and corresponding boolean functions.
|
||||
* These functions are passed the attribute and the current node's value of the attribute.
|
||||
* @property operators
|
||||
* @type object
|
||||
*/
|
||||
operators: {
|
||||
'=': function(attr, val) { return attr === val; }, // Equality
|
||||
'!=': function(attr, val) { return attr !== val; }, // Inequality
|
||||
'~=': function(attr, val) { // Match one of space seperated words
|
||||
var s = ' ';
|
||||
return (s + attr + s).indexOf((s + val + s)) > -1;
|
||||
},
|
||||
'|=': function(attr, val) { return attr === val || attr.slice(0, val.length + 1) === val + '-'; }, // Matches value followed by optional hyphen
|
||||
'^=': function(attr, val) { return attr.indexOf(val) === 0; }, // Match starts with value
|
||||
'$=': function(attr, val) { return attr.slice(-val.length) === val; }, // Match ends with value
|
||||
'*=': function(attr, val) { return attr.indexOf(val) > -1; }, // Match contains value as substring
|
||||
'': function(attr, val) { return attr; } // Just test for existence of attribute
|
||||
},
|
||||
|
||||
/**
|
||||
* List of pseudo-classes and corresponding boolean functions.
|
||||
* These functions are called with the current node, and any value that was parsed with the pseudo regex.
|
||||
* @property pseudos
|
||||
* @type object
|
||||
*/
|
||||
pseudos: {
|
||||
'root': function(node) {
|
||||
return node === node.ownerDocument.documentElement;
|
||||
},
|
||||
|
||||
'nth-child': function(node, val) {
|
||||
return Y.Selector._getNth(node, val);
|
||||
},
|
||||
|
||||
'nth-last-child': function(node, val) {
|
||||
return Y.Selector._getNth(node, val, null, true);
|
||||
},
|
||||
|
||||
'nth-of-type': function(node, val) {
|
||||
return Y.Selector._getNth(node, val, node.tagName);
|
||||
},
|
||||
|
||||
'nth-last-of-type': function(node, val) {
|
||||
return Y.Selector._getNth(node, val, node.tagName, true);
|
||||
},
|
||||
|
||||
'first-child': function(node) {
|
||||
return Y.Selector._getChildren(node.parentNode)[0] === node;
|
||||
},
|
||||
|
||||
'last-child': function(node) {
|
||||
var children = Y.Selector._getChildren(node.parentNode);
|
||||
return children[children.length - 1] === node;
|
||||
},
|
||||
|
||||
'first-of-type': function(node, val) {
|
||||
return Y.Selector._getChildren(node.parentNode, node.tagName)[0];
|
||||
},
|
||||
|
||||
'last-of-type': function(node, val) {
|
||||
var children = Y.Selector._getChildren(node.parentNode, node.tagName);
|
||||
return children[children.length - 1];
|
||||
},
|
||||
|
||||
'only-child': function(node) {
|
||||
var children = Y.Selector._getChildren(node.parentNode);
|
||||
return children.length === 1 && children[0] === node;
|
||||
},
|
||||
|
||||
'only-of-type': function(node) {
|
||||
return Y.Selector._getChildren(node.parentNode, node.tagName).length === 1;
|
||||
},
|
||||
|
||||
'empty': function(node) {
|
||||
return node.childNodes.length === 0;
|
||||
},
|
||||
|
||||
'not': function(node, simple) {
|
||||
return !Y.Selector.test(node, simple);
|
||||
},
|
||||
|
||||
'contains': function(node, str) {
|
||||
var text = node.innerText || node.textContent || '';
|
||||
return text.indexOf(str) > -1;
|
||||
},
|
||||
'checked': function(node) {
|
||||
return node.checked === true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if the supplied node matches the supplied selector.
|
||||
* @method test
|
||||
*
|
||||
* @param {HTMLElement | String} node An id or node reference to the HTMLElement being tested.
|
||||
* @param {string} selector The CSS Selector to test the node against.
|
||||
* @return{boolean} Whether or not the node matches the selector.
|
||||
* @static
|
||||
|
||||
*/
|
||||
test: function(node, selector) {
|
||||
node = Y.Selector.document.getElementById(node) || node;
|
||||
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var groups = selector ? selector.split(',') : [];
|
||||
if (groups.length) {
|
||||
for (var i = 0, len = groups.length; i < len; ++i) {
|
||||
if ( Y.Selector._test(node, groups[i]) ) { // passes if ANY group matches
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return Y.Selector._test(node, selector);
|
||||
},
|
||||
|
||||
_test: function(node, selector, token, deDupe) {
|
||||
token = token || Y.Selector._tokenize(selector).pop() || {};
|
||||
|
||||
if (!node.tagName ||
|
||||
(token.tag !== '*' && node.tagName !== token.tag) ||
|
||||
(deDupe && node._found) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token.attributes.length) {
|
||||
var val,
|
||||
ieFlag,
|
||||
re_urls = Y.Selector._re.urls;
|
||||
|
||||
if (!node.attributes || !node.attributes.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0, attr; attr = token.attributes[i++];) {
|
||||
ieFlag = (re_urls.test(attr[0])) ? 2 : 0;
|
||||
val = node.getAttribute(attr[0], ieFlag);
|
||||
if (val === null || val === undefined) {
|
||||
return false;
|
||||
}
|
||||
if ( Y.Selector.operators[attr[1]] &&
|
||||
!Y.Selector.operators[attr[1]](val, attr[2])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (token.pseudos.length) {
|
||||
for (var i = 0, len = token.pseudos.length; i < len; ++i) {
|
||||
if (Y.Selector.pseudos[token.pseudos[i][0]] &&
|
||||
!Y.Selector.pseudos[token.pseudos[i][0]](node, token.pseudos[i][1])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (token.previous && token.previous.combinator !== ',') ?
|
||||
Y.Selector._combinators[token.previous.combinator](node, token) :
|
||||
true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters a set of nodes based on a given CSS selector.
|
||||
* @method filter
|
||||
*
|
||||
* @param {array} nodes A set of nodes/ids to filter.
|
||||
* @param {string} selector The selector used to test each node.
|
||||
* @return{array} An array of nodes from the supplied array that match the given selector.
|
||||
* @static
|
||||
*/
|
||||
filter: function(nodes, selector) {
|
||||
nodes = nodes || [];
|
||||
|
||||
var node,
|
||||
result = [],
|
||||
tokens = Y.Selector._tokenize(selector);
|
||||
|
||||
if (!nodes.item) { // if not HTMLCollection, handle arrays of ids and/or nodes
|
||||
YAHOO.log('filter: scanning input for HTMLElements/IDs', 'info', 'Selector');
|
||||
for (var i = 0, len = nodes.length; i < len; ++i) {
|
||||
if (!nodes[i].tagName) { // tagName limits to HTMLElements
|
||||
node = Y.Selector.document.getElementById(nodes[i]);
|
||||
if (node) { // skip IDs that return null
|
||||
nodes[i] = node;
|
||||
} else {
|
||||
YAHOO.log('filter: skipping invalid node', 'warn', 'Selector');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = Y.Selector._filter(nodes, Y.Selector._tokenize(selector)[0]);
|
||||
YAHOO.log('filter: returning:' + result.length, 'info', 'Selector');
|
||||
return result;
|
||||
},
|
||||
|
||||
_filter: function(nodes, token, firstOnly, deDupe) {
|
||||
var result = firstOnly ? null : [],
|
||||
foundCache = Y.Selector._foundCache;
|
||||
|
||||
for (var i = 0, len = nodes.length; i < len; i++) {
|
||||
if (! Y.Selector._test(nodes[i], '', token, deDupe)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (firstOnly) {
|
||||
return nodes[i];
|
||||
}
|
||||
if (deDupe) {
|
||||
if (nodes[i]._found) {
|
||||
continue;
|
||||
}
|
||||
nodes[i]._found = true;
|
||||
foundCache[foundCache.length] = nodes[i];
|
||||
}
|
||||
|
||||
result[result.length] = nodes[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves a set of nodes based on a given CSS selector.
|
||||
* @method query
|
||||
*
|
||||
* @param {string} selector The CSS Selector to test the node against.
|
||||
* @param {HTMLElement | String} root optional An id or HTMLElement to start the query from. Defaults to Selector.document.
|
||||
* @param {Boolean} firstOnly optional Whether or not to return only the first match.
|
||||
* @return {Array} An array of nodes that match the given selector.
|
||||
* @static
|
||||
*/
|
||||
query: function(selector, root, firstOnly) {
|
||||
var result = Y.Selector._query(selector, root, firstOnly);
|
||||
YAHOO.log('query: returning ' + result, 'info', 'Selector');
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
_query: function(selector, root, firstOnly, deDupe) {
|
||||
var result = (firstOnly) ? null : [],
|
||||
node;
|
||||
|
||||
if (!selector) {
|
||||
return result;
|
||||
}
|
||||
|
||||
var groups = selector.split(','); // TODO: handle comma in attribute/pseudo
|
||||
|
||||
if (groups.length > 1) {
|
||||
var found;
|
||||
for (var i = 0, len = groups.length; i < len; ++i) {
|
||||
found = arguments.callee(groups[i], root, firstOnly, true);
|
||||
result = firstOnly ? found : result.concat(found);
|
||||
}
|
||||
Y.Selector._clearFoundCache();
|
||||
return result;
|
||||
}
|
||||
|
||||
if (root && !root.nodeName) { // assume ID
|
||||
root = Y.Selector.document.getElementById(root);
|
||||
if (!root) {
|
||||
YAHOO.log('invalid root node provided', 'warn', 'Selector');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
root = root || Y.Selector.document;
|
||||
|
||||
if (root.nodeName !== '#document') { // prepend with root selector
|
||||
Y.Dom.generateId(root); // TODO: cleanup after?
|
||||
selector = root.tagName + '#' + root.id + ' ' + selector;
|
||||
node = root;
|
||||
root = root.ownerDocument;
|
||||
}
|
||||
|
||||
var tokens = Y.Selector._tokenize(selector);
|
||||
var idToken = tokens[Y.Selector._getIdTokenIndex(tokens)],
|
||||
nodes = [],
|
||||
id,
|
||||
token = tokens.pop() || {};
|
||||
|
||||
if (idToken) {
|
||||
id = Y.Selector._getId(idToken.attributes);
|
||||
}
|
||||
|
||||
// use id shortcut when possible
|
||||
if (id) {
|
||||
node = node || Y.Selector.document.getElementById(id);
|
||||
|
||||
if (node && (root.nodeName === '#document' || Y.Dom.isAncestor(root, node))) {
|
||||
if ( Y.Selector._test(node, null, idToken) ) {
|
||||
if (idToken === token) {
|
||||
nodes = [node]; // simple selector
|
||||
} else if (idToken.combinator === ' ' || idToken.combinator === '>') {
|
||||
root = node; // start from here
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (root && !nodes.length) {
|
||||
nodes = root.getElementsByTagName(token.tag);
|
||||
}
|
||||
|
||||
if (nodes.length) {
|
||||
result = Y.Selector._filter(nodes, token, firstOnly, deDupe);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
_clearFoundCache: function() {
|
||||
var foundCache = Y.Selector._foundCache;
|
||||
YAHOO.log('getBySelector: clearing found cache of ' + foundCache.length + ' elements');
|
||||
for (var i = 0, len = foundCache.length; i < len; ++i) {
|
||||
try { // IE no like delete
|
||||
delete foundCache[i]._found;
|
||||
} catch(e) {
|
||||
foundCache[i].removeAttribute('_found');
|
||||
}
|
||||
}
|
||||
foundCache = [];
|
||||
YAHOO.log('getBySelector: done clearing foundCache');
|
||||
},
|
||||
|
||||
|
||||
_getRegExp: function(str, flags) {
|
||||
var regexCache = Y.Selector._regexCache;
|
||||
flags = flags || '';
|
||||
if (!regexCache[str + flags]) {
|
||||
regexCache[str + flags] = new RegExp(str, flags);
|
||||
}
|
||||
return regexCache[str + flags];
|
||||
},
|
||||
|
||||
_getChildren: function() {
|
||||
if (document.documentElement.children) { // document for capability test
|
||||
return function(node, tag) {
|
||||
return (tag) ? node.children.tags(tag) : node.children || [];
|
||||
};
|
||||
} else {
|
||||
return function(node, tag) {
|
||||
if (node._children) {
|
||||
return node._children;
|
||||
}
|
||||
var children = [],
|
||||
childNodes = node.childNodes;
|
||||
|
||||
for (var i = 0, len = childNodes.length; i < len; ++i) {
|
||||
if (childNodes[i].tagName) {
|
||||
if (!tag || childNodes[i].tagName === tag) {
|
||||
children[children.length] = childNodes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
node._children = children;
|
||||
return children;
|
||||
};
|
||||
}
|
||||
}(),
|
||||
|
||||
_combinators: {
|
||||
' ': function(node, token) {
|
||||
while ( (node = node.parentNode) ) {
|
||||
if (Y.Selector._test(node, '', token.previous)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
'>': function(node, token) {
|
||||
return Y.Selector._test(node.parentNode, null, token.previous);
|
||||
},
|
||||
|
||||
'+': function(node, token) {
|
||||
var sib = node.previousSibling;
|
||||
while (sib && sib.nodeType !== 1) {
|
||||
sib = sib.previousSibling;
|
||||
}
|
||||
|
||||
if (sib && Y.Selector._test(sib, null, token.previous)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
'~': function(node, token) {
|
||||
var sib = node.previousSibling;
|
||||
while (sib) {
|
||||
if (sib.nodeType === 1 && Y.Selector._test(sib, null, token.previous)) {
|
||||
return true;
|
||||
}
|
||||
sib = sib.previousSibling;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
an+b = get every _a_th node starting at the _b_th
|
||||
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
|
||||
1n+b = get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
|
||||
an+0 = get every _a_th element, "0" may be omitted
|
||||
*/
|
||||
_getNth: function(node, expr, tag, reverse) {
|
||||
Y.Selector._re.nth.test(expr);
|
||||
var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
|
||||
n = RegExp.$2, // "n"
|
||||
oddeven = RegExp.$3, // "odd" or "even"
|
||||
b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
|
||||
result = [],
|
||||
op;
|
||||
|
||||
var siblings = Y.Selector._getChildren(node.parentNode, tag);
|
||||
|
||||
if (oddeven) {
|
||||
a = 2; // always every other
|
||||
op = '+';
|
||||
n = 'n';
|
||||
b = (oddeven === 'odd') ? 1 : 0;
|
||||
} else if ( isNaN(a) ) {
|
||||
a = (n) ? 1 : 0; // start from the first or no repeat
|
||||
}
|
||||
|
||||
if (a === 0) { // just the first
|
||||
if (reverse) {
|
||||
b = siblings.length - b + 1;
|
||||
}
|
||||
|
||||
if (siblings[b - 1] === node) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (a < 0) {
|
||||
reverse = !!reverse;
|
||||
a = Math.abs(a);
|
||||
}
|
||||
|
||||
if (!reverse) {
|
||||
for (var i = b - 1, len = siblings.length; i < len; i += a) {
|
||||
if ( i >= 0 && siblings[i] === node ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
|
||||
if ( i < len && siblings[i] === node ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_getId: function(attr) {
|
||||
for (var i = 0, len = attr.length; i < len; ++i) {
|
||||
if (attr[i][0] == 'id' && attr[i][1] === '=') {
|
||||
return attr[i][2];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getIdTokenIndex: function(tokens) {
|
||||
for (var i = 0, len = tokens.length; i < len; ++i) {
|
||||
if (Y.Selector._getId(tokens[i].attributes)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
_patterns: {
|
||||
tag: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
|
||||
attributes: /^\[([a-z]+\w*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i,
|
||||
pseudos: /^:([-\w]+)(?:\(['"]?(.+)['"]?\))*/i,
|
||||
combinator: /^\s*([>+~]|\s)\s*/
|
||||
},
|
||||
|
||||
/**
|
||||
Break selector into token units per simple selector.
|
||||
Combinator is attached to left-hand selector.
|
||||
*/
|
||||
_tokenize: function(selector) {
|
||||
var token = {}, // one token per simple selector (left selector holds combinator)
|
||||
tokens = [], // array of tokens
|
||||
id, // unique id for the simple selector (if found)
|
||||
found = false, // whether or not any matches were found this pass
|
||||
patterns = Y.Selector._patterns,
|
||||
match; // the regex match
|
||||
|
||||
selector = Y.Selector._replaceShorthand(selector); // convert ID and CLASS shortcuts to attributes
|
||||
|
||||
/*
|
||||
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.
|
||||
for example:
|
||||
'form:first-child[type=button]:not(button)[lang|=en]'
|
||||
*/
|
||||
do {
|
||||
found = false; // reset after full pass
|
||||
for (var re in patterns) {
|
||||
if (YAHOO.lang.hasOwnProperty(patterns, re)) {
|
||||
if (re != 'tag' && re != 'combinator') { // only one allowed
|
||||
token[re] = token[re] || [];
|
||||
}
|
||||
if ( (match = patterns[re].exec(selector)) ) { // note assignment
|
||||
found = true;
|
||||
if (re != 'tag' && re != 'combinator') { // only one allowed
|
||||
// capture ID for fast path to element
|
||||
if (re === 'attributes' && match[1] === 'id') {
|
||||
token.id = match[3];
|
||||
}
|
||||
|
||||
token[re].push(match.slice(1));
|
||||
} else { // single selector (tag, combinator)
|
||||
token[re] = match[1];
|
||||
}
|
||||
selector = selector.replace(match[0], ''); // strip current match from selector
|
||||
if (re === 'combinator' || !selector.length) { // next token or done
|
||||
token.attributes = Y.Selector._fixAttributes(token.attributes);
|
||||
token.pseudos = token.pseudos || [];
|
||||
token.tag = token.tag ? token.tag.toUpperCase() : '*';
|
||||
tokens.push(token);
|
||||
|
||||
token = { // prep next token
|
||||
previous: token
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (found);
|
||||
|
||||
return tokens;
|
||||
},
|
||||
|
||||
|
||||
_fixAttributes: function(attr) {
|
||||
var aliases = Y.Selector.attrAliases;
|
||||
attr = attr || [];
|
||||
for (var i = 0, len = attr.length; i < len; ++i) {
|
||||
if (aliases[attr[i][0]]) { // convert reserved words, etc
|
||||
attr[i][0] = aliases[attr[i][0]];
|
||||
}
|
||||
if (!attr[i][1]) { // use exists operator
|
||||
attr[i][1] = '';
|
||||
}
|
||||
}
|
||||
return attr;
|
||||
},
|
||||
|
||||
_replaceShorthand: function(selector) {
|
||||
var shorthand = Y.Selector.shorthand;
|
||||
|
||||
//var attrs = selector.match(Y.Selector._patterns.attributes); // pull attributes to avoid false pos on "." and "#"
|
||||
var attrs = selector.match(Y.Selector._re.attr); // pull attributes to avoid false pos on "." and "#"
|
||||
if (attrs) {
|
||||
selector = selector.replace(Y.Selector._re.attr, 'REPLACED_ATTRIBUTE');
|
||||
}
|
||||
for (var re in shorthand) {
|
||||
if (YAHOO.lang.hasOwnProperty(shorthand, re)) {
|
||||
selector = selector.replace(Y.Selector._getRegExp(re, 'gi'), shorthand[re]);
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs) {
|
||||
for (var i = 0, len = attrs.length; i < len; ++i) {
|
||||
selector = selector.replace('REPLACED_ATTRIBUTE', attrs[i]);
|
||||
}
|
||||
}
|
||||
return selector;
|
||||
}
|
||||
};
|
||||
|
||||
if (YAHOO.env.ua.ie && YAHOO.env.ua.ie < 8) { // rewrite class for IE < 8
|
||||
Y.Selector.attrAliases['class'] = 'className';
|
||||
Y.Selector.attrAliases['for'] = 'htmlFor';
|
||||
}
|
||||
|
||||
})();
|
||||
YAHOO.register("selector", YAHOO.util.Selector, {version: "2.7.0", build: "1799"});
|
8
webdir/javascript/yui/selector/selector-min.js
vendored
Normal file
8
webdir/javascript/yui/selector/selector-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
648
webdir/javascript/yui/selector/selector.js
vendored
Normal file
648
webdir/javascript/yui/selector/selector.js
vendored
Normal file
@ -0,0 +1,648 @@
|
||||
/*
|
||||
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
|
||||
Code licensed under the BSD License:
|
||||
http://developer.yahoo.net/yui/license.txt
|
||||
version: 2.7.0
|
||||
*/
|
||||
/**
|
||||
* The selector module provides helper methods allowing CSS3 Selectors to be used with DOM elements.
|
||||
* @module selector
|
||||
* @title Selector Utility
|
||||
* @namespace YAHOO.util
|
||||
* @requires yahoo, dom
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Y = YAHOO.util;
|
||||
|
||||
/**
|
||||
* Provides helper methods for collecting and filtering DOM elements.
|
||||
* @namespace YAHOO.util
|
||||
* @class Selector
|
||||
* @static
|
||||
*/
|
||||
|
||||
Y.Selector = {
|
||||
_foundCache: [],
|
||||
_regexCache: {},
|
||||
|
||||
_re: {
|
||||
nth: /^(?:([-]?\d*)(n){1}|(odd|even)$)*([-+]?\d*)$/,
|
||||
attr: /(\[.*\])/g,
|
||||
urls: /^(?:href|src)/
|
||||
},
|
||||
|
||||
/**
|
||||
* Default document for use queries
|
||||
* @property document
|
||||
* @type object
|
||||
* @default window.document
|
||||
*/
|
||||
document: window.document,
|
||||
/**
|
||||
* Mapping of attributes to aliases, normally to work around HTMLAttributes
|
||||
* that conflict with JS reserved words.
|
||||
* @property attrAliases
|
||||
* @type object
|
||||
*/
|
||||
attrAliases: {
|
||||
},
|
||||
|
||||
/**
|
||||
* Mapping of shorthand tokens to corresponding attribute selector
|
||||
* @property shorthand
|
||||
* @type object
|
||||
*/
|
||||
shorthand: {
|
||||
//'(?:(?:[^\\)\\]\\s*>+~,]+)(?:-?[_a-z]+[-\\w]))+#(-?[_a-z]+[-\\w]*)': '[id=$1]',
|
||||
'\\#(-?[_a-z]+[-\\w]*)': '[id=$1]',
|
||||
'\\.(-?[_a-z]+[-\\w]*)': '[class~=$1]'
|
||||
},
|
||||
|
||||
/**
|
||||
* List of operators and corresponding boolean functions.
|
||||
* These functions are passed the attribute and the current node's value of the attribute.
|
||||
* @property operators
|
||||
* @type object
|
||||
*/
|
||||
operators: {
|
||||
'=': function(attr, val) { return attr === val; }, // Equality
|
||||
'!=': function(attr, val) { return attr !== val; }, // Inequality
|
||||
'~=': function(attr, val) { // Match one of space seperated words
|
||||
var s = ' ';
|
||||
return (s + attr + s).indexOf((s + val + s)) > -1;
|
||||
},
|
||||
'|=': function(attr, val) { return attr === val || attr.slice(0, val.length + 1) === val + '-'; }, // Matches value followed by optional hyphen
|
||||
'^=': function(attr, val) { return attr.indexOf(val) === 0; }, // Match starts with value
|
||||
'$=': function(attr, val) { return attr.slice(-val.length) === val; }, // Match ends with value
|
||||
'*=': function(attr, val) { return attr.indexOf(val) > -1; }, // Match contains value as substring
|
||||
'': function(attr, val) { return attr; } // Just test for existence of attribute
|
||||
},
|
||||
|
||||
/**
|
||||
* List of pseudo-classes and corresponding boolean functions.
|
||||
* These functions are called with the current node, and any value that was parsed with the pseudo regex.
|
||||
* @property pseudos
|
||||
* @type object
|
||||
*/
|
||||
pseudos: {
|
||||
'root': function(node) {
|
||||
return node === node.ownerDocument.documentElement;
|
||||
},
|
||||
|
||||
'nth-child': function(node, val) {
|
||||
return Y.Selector._getNth(node, val);
|
||||
},
|
||||
|
||||
'nth-last-child': function(node, val) {
|
||||
return Y.Selector._getNth(node, val, null, true);
|
||||
},
|
||||
|
||||
'nth-of-type': function(node, val) {
|
||||
return Y.Selector._getNth(node, val, node.tagName);
|
||||
},
|
||||
|
||||
'nth-last-of-type': function(node, val) {
|
||||
return Y.Selector._getNth(node, val, node.tagName, true);
|
||||
},
|
||||
|
||||
'first-child': function(node) {
|
||||
return Y.Selector._getChildren(node.parentNode)[0] === node;
|
||||
},
|
||||
|
||||
'last-child': function(node) {
|
||||
var children = Y.Selector._getChildren(node.parentNode);
|
||||
return children[children.length - 1] === node;
|
||||
},
|
||||
|
||||
'first-of-type': function(node, val) {
|
||||
return Y.Selector._getChildren(node.parentNode, node.tagName)[0];
|
||||
},
|
||||
|
||||
'last-of-type': function(node, val) {
|
||||
var children = Y.Selector._getChildren(node.parentNode, node.tagName);
|
||||
return children[children.length - 1];
|
||||
},
|
||||
|
||||
'only-child': function(node) {
|
||||
var children = Y.Selector._getChildren(node.parentNode);
|
||||
return children.length === 1 && children[0] === node;
|
||||
},
|
||||
|
||||
'only-of-type': function(node) {
|
||||
return Y.Selector._getChildren(node.parentNode, node.tagName).length === 1;
|
||||
},
|
||||
|
||||
'empty': function(node) {
|
||||
return node.childNodes.length === 0;
|
||||
},
|
||||
|
||||
'not': function(node, simple) {
|
||||
return !Y.Selector.test(node, simple);
|
||||
},
|
||||
|
||||
'contains': function(node, str) {
|
||||
var text = node.innerText || node.textContent || '';
|
||||
return text.indexOf(str) > -1;
|
||||
},
|
||||
'checked': function(node) {
|
||||
return node.checked === true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Test if the supplied node matches the supplied selector.
|
||||
* @method test
|
||||
*
|
||||
* @param {HTMLElement | String} node An id or node reference to the HTMLElement being tested.
|
||||
* @param {string} selector The CSS Selector to test the node against.
|
||||
* @return{boolean} Whether or not the node matches the selector.
|
||||
* @static
|
||||
|
||||
*/
|
||||
test: function(node, selector) {
|
||||
node = Y.Selector.document.getElementById(node) || node;
|
||||
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var groups = selector ? selector.split(',') : [];
|
||||
if (groups.length) {
|
||||
for (var i = 0, len = groups.length; i < len; ++i) {
|
||||
if ( Y.Selector._test(node, groups[i]) ) { // passes if ANY group matches
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return Y.Selector._test(node, selector);
|
||||
},
|
||||
|
||||
_test: function(node, selector, token, deDupe) {
|
||||
token = token || Y.Selector._tokenize(selector).pop() || {};
|
||||
|
||||
if (!node.tagName ||
|
||||
(token.tag !== '*' && node.tagName !== token.tag) ||
|
||||
(deDupe && node._found) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token.attributes.length) {
|
||||
var val,
|
||||
ieFlag,
|
||||
re_urls = Y.Selector._re.urls;
|
||||
|
||||
if (!node.attributes || !node.attributes.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0, attr; attr = token.attributes[i++];) {
|
||||
ieFlag = (re_urls.test(attr[0])) ? 2 : 0;
|
||||
val = node.getAttribute(attr[0], ieFlag);
|
||||
if (val === null || val === undefined) {
|
||||
return false;
|
||||
}
|
||||
if ( Y.Selector.operators[attr[1]] &&
|
||||
!Y.Selector.operators[attr[1]](val, attr[2])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (token.pseudos.length) {
|
||||
for (var i = 0, len = token.pseudos.length; i < len; ++i) {
|
||||
if (Y.Selector.pseudos[token.pseudos[i][0]] &&
|
||||
!Y.Selector.pseudos[token.pseudos[i][0]](node, token.pseudos[i][1])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (token.previous && token.previous.combinator !== ',') ?
|
||||
Y.Selector._combinators[token.previous.combinator](node, token) :
|
||||
true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters a set of nodes based on a given CSS selector.
|
||||
* @method filter
|
||||
*
|
||||
* @param {array} nodes A set of nodes/ids to filter.
|
||||
* @param {string} selector The selector used to test each node.
|
||||
* @return{array} An array of nodes from the supplied array that match the given selector.
|
||||
* @static
|
||||
*/
|
||||
filter: function(nodes, selector) {
|
||||
nodes = nodes || [];
|
||||
|
||||
var node,
|
||||
result = [],
|
||||
tokens = Y.Selector._tokenize(selector);
|
||||
|
||||
if (!nodes.item) { // if not HTMLCollection, handle arrays of ids and/or nodes
|
||||
for (var i = 0, len = nodes.length; i < len; ++i) {
|
||||
if (!nodes[i].tagName) { // tagName limits to HTMLElements
|
||||
node = Y.Selector.document.getElementById(nodes[i]);
|
||||
if (node) { // skip IDs that return null
|
||||
nodes[i] = node;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = Y.Selector._filter(nodes, Y.Selector._tokenize(selector)[0]);
|
||||
return result;
|
||||
},
|
||||
|
||||
_filter: function(nodes, token, firstOnly, deDupe) {
|
||||
var result = firstOnly ? null : [],
|
||||
foundCache = Y.Selector._foundCache;
|
||||
|
||||
for (var i = 0, len = nodes.length; i < len; i++) {
|
||||
if (! Y.Selector._test(nodes[i], '', token, deDupe)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (firstOnly) {
|
||||
return nodes[i];
|
||||
}
|
||||
if (deDupe) {
|
||||
if (nodes[i]._found) {
|
||||
continue;
|
||||
}
|
||||
nodes[i]._found = true;
|
||||
foundCache[foundCache.length] = nodes[i];
|
||||
}
|
||||
|
||||
result[result.length] = nodes[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves a set of nodes based on a given CSS selector.
|
||||
* @method query
|
||||
*
|
||||
* @param {string} selector The CSS Selector to test the node against.
|
||||
* @param {HTMLElement | String} root optional An id or HTMLElement to start the query from. Defaults to Selector.document.
|
||||
* @param {Boolean} firstOnly optional Whether or not to return only the first match.
|
||||
* @return {Array} An array of nodes that match the given selector.
|
||||
* @static
|
||||
*/
|
||||
query: function(selector, root, firstOnly) {
|
||||
var result = Y.Selector._query(selector, root, firstOnly);
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
_query: function(selector, root, firstOnly, deDupe) {
|
||||
var result = (firstOnly) ? null : [],
|
||||
node;
|
||||
|
||||
if (!selector) {
|
||||
return result;
|
||||
}
|
||||
|
||||
var groups = selector.split(','); // TODO: handle comma in attribute/pseudo
|
||||
|
||||
if (groups.length > 1) {
|
||||
var found;
|
||||
for (var i = 0, len = groups.length; i < len; ++i) {
|
||||
found = arguments.callee(groups[i], root, firstOnly, true);
|
||||
result = firstOnly ? found : result.concat(found);
|
||||
}
|
||||
Y.Selector._clearFoundCache();
|
||||
return result;
|
||||
}
|
||||
|
||||
if (root && !root.nodeName) { // assume ID
|
||||
root = Y.Selector.document.getElementById(root);
|
||||
if (!root) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
root = root || Y.Selector.document;
|
||||
|
||||
if (root.nodeName !== '#document') { // prepend with root selector
|
||||
Y.Dom.generateId(root); // TODO: cleanup after?
|
||||
selector = root.tagName + '#' + root.id + ' ' + selector;
|
||||
node = root;
|
||||
root = root.ownerDocument;
|
||||
}
|
||||
|
||||
var tokens = Y.Selector._tokenize(selector);
|
||||
var idToken = tokens[Y.Selector._getIdTokenIndex(tokens)],
|
||||
nodes = [],
|
||||
id,
|
||||
token = tokens.pop() || {};
|
||||
|
||||
if (idToken) {
|
||||
id = Y.Selector._getId(idToken.attributes);
|
||||
}
|
||||
|
||||
// use id shortcut when possible
|
||||
if (id) {
|
||||
node = node || Y.Selector.document.getElementById(id);
|
||||
|
||||
if (node && (root.nodeName === '#document' || Y.Dom.isAncestor(root, node))) {
|
||||
if ( Y.Selector._test(node, null, idToken) ) {
|
||||
if (idToken === token) {
|
||||
nodes = [node]; // simple selector
|
||||
} else if (idToken.combinator === ' ' || idToken.combinator === '>') {
|
||||
root = node; // start from here
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (root && !nodes.length) {
|
||||
nodes = root.getElementsByTagName(token.tag);
|
||||
}
|
||||
|
||||
if (nodes.length) {
|
||||
result = Y.Selector._filter(nodes, token, firstOnly, deDupe);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
_clearFoundCache: function() {
|
||||
var foundCache = Y.Selector._foundCache;
|
||||
for (var i = 0, len = foundCache.length; i < len; ++i) {
|
||||
try { // IE no like delete
|
||||
delete foundCache[i]._found;
|
||||
} catch(e) {
|
||||
foundCache[i].removeAttribute('_found');
|
||||
}
|
||||
}
|
||||
foundCache = [];
|
||||
},
|
||||
|
||||
|
||||
_getRegExp: function(str, flags) {
|
||||
var regexCache = Y.Selector._regexCache;
|
||||
flags = flags || '';
|
||||
if (!regexCache[str + flags]) {
|
||||
regexCache[str + flags] = new RegExp(str, flags);
|
||||
}
|
||||
return regexCache[str + flags];
|
||||
},
|
||||
|
||||
_getChildren: function() {
|
||||
if (document.documentElement.children) { // document for capability test
|
||||
return function(node, tag) {
|
||||
return (tag) ? node.children.tags(tag) : node.children || [];
|
||||
};
|
||||
} else {
|
||||
return function(node, tag) {
|
||||
if (node._children) {
|
||||
return node._children;
|
||||
}
|
||||
var children = [],
|
||||
childNodes = node.childNodes;
|
||||
|
||||
for (var i = 0, len = childNodes.length; i < len; ++i) {
|
||||
if (childNodes[i].tagName) {
|
||||
if (!tag || childNodes[i].tagName === tag) {
|
||||
children[children.length] = childNodes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
node._children = children;
|
||||
return children;
|
||||
};
|
||||
}
|
||||
}(),
|
||||
|
||||
_combinators: {
|
||||
' ': function(node, token) {
|
||||
while ( (node = node.parentNode) ) {
|
||||
if (Y.Selector._test(node, '', token.previous)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
'>': function(node, token) {
|
||||
return Y.Selector._test(node.parentNode, null, token.previous);
|
||||
},
|
||||
|
||||
'+': function(node, token) {
|
||||
var sib = node.previousSibling;
|
||||
while (sib && sib.nodeType !== 1) {
|
||||
sib = sib.previousSibling;
|
||||
}
|
||||
|
||||
if (sib && Y.Selector._test(sib, null, token.previous)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
'~': function(node, token) {
|
||||
var sib = node.previousSibling;
|
||||
while (sib) {
|
||||
if (sib.nodeType === 1 && Y.Selector._test(sib, null, token.previous)) {
|
||||
return true;
|
||||
}
|
||||
sib = sib.previousSibling;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
an+b = get every _a_th node starting at the _b_th
|
||||
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
|
||||
1n+b = get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
|
||||
an+0 = get every _a_th element, "0" may be omitted
|
||||
*/
|
||||
_getNth: function(node, expr, tag, reverse) {
|
||||
Y.Selector._re.nth.test(expr);
|
||||
var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
|
||||
n = RegExp.$2, // "n"
|
||||
oddeven = RegExp.$3, // "odd" or "even"
|
||||
b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
|
||||
result = [],
|
||||
op;
|
||||
|
||||
var siblings = Y.Selector._getChildren(node.parentNode, tag);
|
||||
|
||||
if (oddeven) {
|
||||
a = 2; // always every other
|
||||
op = '+';
|
||||
n = 'n';
|
||||
b = (oddeven === 'odd') ? 1 : 0;
|
||||
} else if ( isNaN(a) ) {
|
||||
a = (n) ? 1 : 0; // start from the first or no repeat
|
||||
}
|
||||
|
||||
if (a === 0) { // just the first
|
||||
if (reverse) {
|
||||
b = siblings.length - b + 1;
|
||||
}
|
||||
|
||||
if (siblings[b - 1] === node) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (a < 0) {
|
||||
reverse = !!reverse;
|
||||
a = Math.abs(a);
|
||||
}
|
||||
|
||||
if (!reverse) {
|
||||
for (var i = b - 1, len = siblings.length; i < len; i += a) {
|
||||
if ( i >= 0 && siblings[i] === node ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
|
||||
if ( i < len && siblings[i] === node ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_getId: function(attr) {
|
||||
for (var i = 0, len = attr.length; i < len; ++i) {
|
||||
if (attr[i][0] == 'id' && attr[i][1] === '=') {
|
||||
return attr[i][2];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getIdTokenIndex: function(tokens) {
|
||||
for (var i = 0, len = tokens.length; i < len; ++i) {
|
||||
if (Y.Selector._getId(tokens[i].attributes)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
_patterns: {
|
||||
tag: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
|
||||
attributes: /^\[([a-z]+\w*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i,
|
||||
pseudos: /^:([-\w]+)(?:\(['"]?(.+)['"]?\))*/i,
|
||||
combinator: /^\s*([>+~]|\s)\s*/
|
||||
},
|
||||
|
||||
/**
|
||||
Break selector into token units per simple selector.
|
||||
Combinator is attached to left-hand selector.
|
||||
*/
|
||||
_tokenize: function(selector) {
|
||||
var token = {}, // one token per simple selector (left selector holds combinator)
|
||||
tokens = [], // array of tokens
|
||||
id, // unique id for the simple selector (if found)
|
||||
found = false, // whether or not any matches were found this pass
|
||||
patterns = Y.Selector._patterns,
|
||||
match; // the regex match
|
||||
|
||||
selector = Y.Selector._replaceShorthand(selector); // convert ID and CLASS shortcuts to attributes
|
||||
|
||||
/*
|
||||
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.
|
||||
for example:
|
||||
'form:first-child[type=button]:not(button)[lang|=en]'
|
||||
*/
|
||||
do {
|
||||
found = false; // reset after full pass
|
||||
for (var re in patterns) {
|
||||
if (YAHOO.lang.hasOwnProperty(patterns, re)) {
|
||||
if (re != 'tag' && re != 'combinator') { // only one allowed
|
||||
token[re] = token[re] || [];
|
||||
}
|
||||
if ( (match = patterns[re].exec(selector)) ) { // note assignment
|
||||
found = true;
|
||||
if (re != 'tag' && re != 'combinator') { // only one allowed
|
||||
// capture ID for fast path to element
|
||||
if (re === 'attributes' && match[1] === 'id') {
|
||||
token.id = match[3];
|
||||
}
|
||||
|
||||
token[re].push(match.slice(1));
|
||||
} else { // single selector (tag, combinator)
|
||||
token[re] = match[1];
|
||||
}
|
||||
selector = selector.replace(match[0], ''); // strip current match from selector
|
||||
if (re === 'combinator' || !selector.length) { // next token or done
|
||||
token.attributes = Y.Selector._fixAttributes(token.attributes);
|
||||
token.pseudos = token.pseudos || [];
|
||||
token.tag = token.tag ? token.tag.toUpperCase() : '*';
|
||||
tokens.push(token);
|
||||
|
||||
token = { // prep next token
|
||||
previous: token
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (found);
|
||||
|
||||
return tokens;
|
||||
},
|
||||
|
||||
|
||||
_fixAttributes: function(attr) {
|
||||
var aliases = Y.Selector.attrAliases;
|
||||
attr = attr || [];
|
||||
for (var i = 0, len = attr.length; i < len; ++i) {
|
||||
if (aliases[attr[i][0]]) { // convert reserved words, etc
|
||||
attr[i][0] = aliases[attr[i][0]];
|
||||
}
|
||||
if (!attr[i][1]) { // use exists operator
|
||||
attr[i][1] = '';
|
||||
}
|
||||
}
|
||||
return attr;
|
||||
},
|
||||
|
||||
_replaceShorthand: function(selector) {
|
||||
var shorthand = Y.Selector.shorthand;
|
||||
|
||||
//var attrs = selector.match(Y.Selector._patterns.attributes); // pull attributes to avoid false pos on "." and "#"
|
||||
var attrs = selector.match(Y.Selector._re.attr); // pull attributes to avoid false pos on "." and "#"
|
||||
if (attrs) {
|
||||
selector = selector.replace(Y.Selector._re.attr, 'REPLACED_ATTRIBUTE');
|
||||
}
|
||||
for (var re in shorthand) {
|
||||
if (YAHOO.lang.hasOwnProperty(shorthand, re)) {
|
||||
selector = selector.replace(Y.Selector._getRegExp(re, 'gi'), shorthand[re]);
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs) {
|
||||
for (var i = 0, len = attrs.length; i < len; ++i) {
|
||||
selector = selector.replace('REPLACED_ATTRIBUTE', attrs[i]);
|
||||
}
|
||||
}
|
||||
return selector;
|
||||
}
|
||||
};
|
||||
|
||||
if (YAHOO.env.ua.ie && YAHOO.env.ua.ie < 8) { // rewrite class for IE < 8
|
||||
Y.Selector.attrAliases['class'] = 'className';
|
||||
Y.Selector.attrAliases['for'] = 'htmlFor';
|
||||
}
|
||||
|
||||
})();
|
||||
YAHOO.register("selector", YAHOO.util.Selector, {version: "2.7.0", build: "1799"});
|
Reference in New Issue
Block a user