--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui3.0.0/build/dom/selector.js Mon Nov 23 15:14:29 2009 +0100
@@ -0,0 +1,673 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 3.0.0
+build: 1549
+*/
+YUI.add('selector-native', function(Y) {
+
+(function(Y) {
+/**
+ * The selector-native module provides support for native querySelector
+ * @module dom
+ * @submodule selector-native
+ * @for Selector
+ */
+
+/**
+ * Provides support for using CSS selectors to query the DOM
+ * @class Selector
+ * @static
+ * @for Selector
+ */
+
+Y.namespace('Selector'); // allow native module to standalone
+
+var COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
+ OWNER_DOCUMENT = 'ownerDocument',
+ TMP_PREFIX = 'yui-tmp-',
+ g_counter = 0;
+
+var Selector = {
+ _foundCache: [],
+
+ useNative: true,
+
+ _compare: ('sourceIndex' in document.documentElement) ?
+ function(nodeA, nodeB) {
+ var a = nodeA.sourceIndex,
+ b = nodeB.sourceIndex;
+
+ if (a === b) {
+ return 0;
+ } else if (a > b) {
+ return 1;
+ }
+
+ return -1;
+
+ } : (document.documentElement[COMPARE_DOCUMENT_POSITION] ?
+ function(nodeA, nodeB) {
+ if (nodeA[COMPARE_DOCUMENT_POSITION](nodeB) & 4) {
+ return -1;
+ } else {
+ return 1;
+ }
+ } :
+ function(nodeA, nodeB) {
+ var rangeA, rangeB, compare;
+ if (nodeA && nodeB) {
+ rangeA = nodeA[OWNER_DOCUMENT].createRange();
+ rangeA.setStart(nodeA, 0);
+ rangeB = nodeB[OWNER_DOCUMENT].createRange();
+ rangeB.setStart(nodeB, 0);
+ compare = rangeA.compareBoundaryPoints(1, rangeB); // 1 === Range.START_TO_END
+ }
+
+ return compare;
+
+ }),
+
+ _sort: function(nodes) {
+ if (nodes) {
+ nodes = Y.Array(nodes, 0, true);
+ if (nodes.sort) {
+ nodes.sort(Selector._compare);
+ }
+ }
+
+ return nodes;
+ },
+
+ _deDupe: function(nodes) {
+ var ret = [],
+ i, node;
+
+ for (i = 0; (node = nodes[i++]);) {
+ if (!node._found) {
+ ret[ret.length] = node;
+ node._found = true;
+ }
+ }
+
+ for (i = 0; (node = ret[i++]);) {
+ node._found = null;
+ node.removeAttribute('_found');
+ }
+
+ return ret;
+ },
+
+ /**
+ * 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} 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.
+ * @static
+ */
+ query: function(selector, root, firstOnly, skipNative) {
+ root = root || Y.config.doc;
+ var ret = [],
+ useNative = (Y.Selector.useNative && document.querySelector && !skipNative),
+ queries = [[selector, root]],
+ query,
+ result,
+ i,
+ fn = (useNative) ? Y.Selector._nativeQuery : Y.Selector._bruteQuery;
+
+ if (selector && fn) {
+ // split group into seperate queries
+ if (!skipNative && // already done if skipping
+ (!useNative || root.tagName)) { // split native when element scoping is needed
+ queries = Selector._splitQueries(selector, root);
+ }
+
+ for (i = 0; (query = queries[i++]);) {
+ result = fn(query[0], query[1], firstOnly);
+ if (!firstOnly) { // coerce DOM Collection to Array
+ result = Y.Array(result, 0, true);
+ }
+ if (result) {
+ ret = ret.concat(result);
+ }
+ }
+
+ if (queries.length > 1) { // remove dupes and sort by doc order
+ ret = Selector._sort(Selector._deDupe(ret));
+ }
+ }
+
+ return (firstOnly) ? (ret[0] || null) : ret;
+
+ },
+
+ // allows element scoped queries to begin with combinator
+ // e.g. query('> p', document.body) === query('body > p')
+ _splitQueries: function(selector, node) {
+ var groups = selector.split(','),
+ queries = [],
+ prefix = '',
+ i, len;
+
+ if (node) {
+ // enforce for element scoping
+ if (node.tagName) {
+ node.id = node.id || Y.guid();
+ prefix = '#' + node.id + ' ';
+ }
+
+ for (i = 0, len = groups.length; i < len; ++i) {
+ selector = prefix + groups[i];
+ queries.push([selector, node]);
+ }
+ }
+
+ return queries;
+ },
+
+ _nativeQuery: function(selector, root, one) {
+ try {
+ return root['querySelector' + (one ? '' : 'All')](selector);
+ } catch(e) { // fallback to brute if available
+ return Y.Selector.query(selector, root, one, true); // redo with skipNative true
+ }
+ },
+
+ filter: function(nodes, selector) {
+ var ret = [],
+ i, node;
+
+ if (nodes && selector) {
+ for (i = 0; (node = nodes[i++]);) {
+ if (Y.Selector.test(node, selector)) {
+ ret[ret.length] = node;
+ }
+ }
+ } else {
+ }
+
+ return ret;
+ },
+
+ test: function(node, selector, root) {
+ var ret = false,
+ groups = selector.split(','),
+ item,
+ i, group;
+
+ if (node && node.tagName) { // only test HTMLElements
+ root = root || node.ownerDocument;
+
+ if (!node.id) {
+ node.id = TMP_PREFIX + g_counter++;
+ }
+ for (i = 0; (group = groups[i++]);) { // TODO: off-dom test
+ group += '#' + node.id; // add ID for uniqueness
+ item = Y.Selector.query(group, root, true);
+ ret = (item === node);
+ if (ret) {
+ break;
+ }
+ }
+ }
+
+ return ret;
+ }
+};
+
+Y.mix(Y.Selector, Selector, true);
+
+})(Y);
+
+
+}, '3.0.0' ,{requires:['dom-base']});
+YUI.add('selector-css2', function(Y) {
+
+/**
+ * The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements.
+ * @module dom
+ * @submodule selector-css2
+ * @for Selector
+ */
+
+/**
+ * Provides helper methods for collecting and filtering DOM elements.
+ */
+
+var PARENT_NODE = 'parentNode',
+ TAG_NAME = 'tagName',
+ ATTRIBUTES = 'attributes',
+ COMBINATOR = 'combinator',
+ PSEUDOS = 'pseudos',
+
+ Selector = Y.Selector,
+
+ SelectorCSS2 = {
+ SORT_RESULTS: true,
+ _children: function(node, tag) {
+ var ret = node.children,
+ i,
+ children = [],
+ childNodes,
+ child;
+
+ if (node.children && tag && node.children.tags) {
+ children = node.children.tags(tag);
+ } else if ((!ret && node[TAG_NAME]) || (ret && tag)) { // only HTMLElements have children
+ childNodes = ret || node.childNodes;
+ ret = [];
+ for (i = 0; (child = childNodes[i++]);) {
+ if (child.tagName) {
+ if (!tag || tag === child.tagName) {
+ ret.push(child);
+ }
+ }
+ }
+ }
+
+ return ret || [];
+ },
+
+ _regexCache: {},
+
+ _re: {
+ attr: /(\[.*\])/g,
+ pseudos: /:([\-\w]+(?:\(?:['"]?(.+)['"]?\)))*/i
+ },
+
+ /**
+ * Mapping of shorthand tokens to corresponding attribute selector
+ * @property shorthand
+ * @type object
+ */
+ shorthand: {
+ '\\#(-?[_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.
+ * @property operators
+ * @type object
+ */
+ operators: {
+ '': 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
+ },
+
+ pseudos: {
+ 'first-child': function(node) {
+ return Y.Selector._children(node[PARENT_NODE])[0] === node;
+ }
+ },
+
+ _bruteQuery: function(selector, root, firstOnly) {
+ var ret = [],
+ nodes = [],
+ tokens = Selector._tokenize(selector),
+ token = tokens[tokens.length - 1],
+ rootDoc = Y.DOM._getDoc(root),
+ id,
+ className,
+ tagName;
+
+
+ // if we have an initial ID, set to root when in document
+ if (tokens[0] && rootDoc === root &&
+ (id = tokens[0].id) &&
+ rootDoc.getElementById(id)) {
+ root = rootDoc.getElementById(id);
+ }
+
+ if (token) {
+ // prefilter nodes
+ id = token.id;
+ className = token.className;
+ tagName = token.tagName || '*';
+
+ // try ID first
+ if (id) {
+ if (rootDoc.getElementById(id)) { // if in document
+ nodes = [rootDoc.getElementById(id)]; // TODO: DOM.byId?
+ }
+ // try className if supported
+ } else if (className) {
+ nodes = root.getElementsByClassName(className);
+ } else if (tagName) { // default to tagName
+ nodes = root.getElementsByTagName(tagName || '*');
+ }
+
+ if (nodes.length) {
+ ret = Selector._filterNodes(nodes, tokens, firstOnly);
+ }
+ }
+
+ return ret;
+ },
+
+ _filterNodes: function(nodes, tokens, firstOnly) {
+ var i = 0,
+ j,
+ len = tokens.length,
+ n = len - 1,
+ result = [],
+ node = nodes[0],
+ tmpNode = node,
+ getters = Y.Selector.getters,
+ operator,
+ combinator,
+ token,
+ path,
+ pass,
+ //FUNCTION = 'function',
+ value,
+ tests,
+ test;
+
+ //do {
+ for (i = 0; (tmpNode = node = nodes[i++]);) {
+ n = len - 1;
+ path = null;
+
+ testLoop:
+ while (tmpNode && tmpNode.tagName) {
+ token = tokens[n];
+ tests = token.tests;
+ j = tests.length;
+ if (j && !pass) {
+ while ((test = tests[--j])) {
+ operator = test[1];
+ if (getters[test[0]]) {
+ value = getters[test[0]](tmpNode, test[0]);
+ } else {
+ 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])) {
+ while (tmpNode &&
+ (!tmpNode.tagName ||
+ (token.tagName && token.tagName !== tmpNode.tagName))
+ ) {
+ tmpNode = tmpNode[path];
+ }
+ }
+ continue testLoop;
+ }
+ }
+ }
+
+ n--; // move to next token
+ // now that we've passed the test, move up the tree by combinator
+ if (!pass && (combinator = token.combinator)) {
+ path = combinator.axis;
+ tmpNode = tmpNode[path];
+
+ // skip non element nodes
+ while (tmpNode && !tmpNode.tagName) {
+ tmpNode = tmpNode[path];
+ }
+
+ if (combinator.direct) { // one pass only
+ path = null;
+ }
+
+ } else { // success if we made it this far
+ result.push(node);
+ if (firstOnly) {
+ return result;
+ }
+ break;
+ }
+ }
+ }// while (tmpNode = node = nodes[++i]);
+ node = tmpNode = null;
+ return result;
+ },
+
+ _getRegExp: function(str, flags) {
+ var regexCache = Selector._regexCache;
+ flags = flags || '';
+ if (!regexCache[str + flags]) {
+ regexCache[str + flags] = new RegExp(str, flags);
+ }
+ return regexCache[str + flags];
+ },
+
+ combinators: {
+ ' ': {
+ axis: 'parentNode'
+ },
+
+ '>': {
+ axis: 'parentNode',
+ direct: true
+ },
+
+
+ '+': {
+ axis: 'previousSibling',
+ direct: true
+ }
+ },
+
+ _parsers: [
+ {
+ name: ATTRIBUTES,
+ re: /^\[([a-z]+\w*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i,
+ fn: function(match, token) {
+ var operator = match[2] || '',
+ operators = Y.Selector.operators,
+ test;
+
+ // add prefiltering for ID and CLASS
+ if ((match[1] === 'id' && operator === '=') ||
+ (match[1] === 'className' &&
+ document.getElementsByClassName &&
+ (operator === '~=' || operator === '='))) {
+ token.prefilter = match[1];
+ token[match[1]] = match[3];
+ }
+
+ // add tests
+ if (operator in operators) {
+ test = operators[operator];
+ if (typeof test === 'string') {
+ test = Y.Selector._getRegExp(test.replace('{val}', match[3]));
+ }
+ match[2] = test;
+ }
+ if (!token.last || token.prefilter !== match[1]) {
+ return match.slice(1);
+ }
+ }
+
+ },
+ {
+ name: TAG_NAME,
+ re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
+ fn: function(match, token) {
+ var tag = match[1].toUpperCase();
+ token.tagName = tag;
+
+ if (tag !== '*' && (!token.last || token.prefilter)) {
+ return [TAG_NAME, '=', tag];
+ }
+ if (!token.prefilter) {
+ token.prefilter = 'tagName';
+ }
+ }
+ },
+ {
+ name: COMBINATOR,
+ re: /^\s*([>+~]|\s)\s*/,
+ fn: function(match, token) {
+ }
+ },
+ {
+ name: PSEUDOS,
+ re: /^:([\-\w]+)(?:\(['"]?(.+)['"]?\))*/i,
+ fn: function(match, token) {
+ var test = Selector[PSEUDOS][match[1]];
+ if (test) { // reorder match array
+ return [match[2], test];
+ } else { // selector token not supported (possibly missing CSS3 module)
+ return false;
+ }
+ }
+ }
+ ],
+
+ _getToken: function(token) {
+ return {
+ tagName: null,
+ id: null,
+ className: null,
+ attributes: {},
+ combinator: null,
+ tests: []
+ };
+ },
+
+ /**
+ Break selector into token units per simple selector.
+ Combinator is attached to the previous token.
+ */
+ _tokenize: function(selector) {
+ selector = selector || '';
+ selector = Selector._replaceShorthand(Y.Lang.trim(selector));
+ var token = Selector._getToken(), // one token per simple selector (left selector holds combinator)
+ query = selector, // original query for debug report
+ tokens = [], // array of tokens
+ found = false, // whether or not any matches were found this pass
+ match, // the regex match
+ test,
+ i, parser;
+
+ /*
+ 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]'
+ */
+ outer:
+ do {
+ found = false; // reset after full pass
+ for (i = 0; (parser = Selector._parsers[i++]);) {
+ if ( (match = parser.re.exec(selector)) ) { // note assignment
+ if (parser !== COMBINATOR ) {
+ token.selector = selector;
+ }
+ selector = selector.replace(match[0], ''); // strip current match from selector
+ if (!selector.length) {
+ token.last = true;
+ }
+
+ if (Selector._attrFilters[match[1]]) { // convert class to className, etc.
+ match[1] = Selector._attrFilters[match[1]];
+ }
+
+ test = parser.fn(match, token);
+ if (test === false) { // selector not supported
+ found = false;
+ break outer;
+ } else if (test) {
+ token.tests.push(test);
+ }
+
+ if (!selector.length || parser.name === COMBINATOR) {
+ tokens.push(token);
+ token = Selector._getToken(token);
+ if (parser.name === COMBINATOR) {
+ token.combinator = Y.Selector.combinators[match[1]];
+ }
+ }
+ found = true;
+ }
+ }
+ } while (found && selector.length);
+
+ if (!found || selector.length) { // not fully parsed
+ tokens = [];
+ }
+ return tokens;
+ },
+
+ _replaceShorthand: function(selector) {
+ var shorthand = Selector.shorthand,
+ attrs = selector.match(Selector._re.attr), // pull attributes to avoid false pos on "." and "#"
+ pseudos = selector.match(Selector._re.pseudos), // pull attributes to avoid false pos on "." and "#"
+ re, i, len;
+
+ if (pseudos) {
+ selector = selector.replace(Selector._re.pseudos, '!!REPLACED_PSEUDO!!');
+ }
+
+ if (attrs) {
+ selector = selector.replace(Selector._re.attr, '!!REPLACED_ATTRIBUTE!!');
+ }
+
+ for (re in shorthand) {
+ if (shorthand.hasOwnProperty(re)) {
+ selector = selector.replace(Selector._getRegExp(re, 'gi'), shorthand[re]);
+ }
+ }
+
+ if (attrs) {
+ for (i = 0, len = attrs.length; i < len; ++i) {
+ selector = selector.replace('!!REPLACED_ATTRIBUTE!!', attrs[i]);
+ }
+ }
+ if (pseudos) {
+ for (i = 0, len = pseudos.length; i < len; ++i) {
+ selector = selector.replace('!!REPLACED_PSEUDO!!', pseudos[i]);
+ }
+ }
+ return selector;
+ },
+
+ _attrFilters: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+
+ getters: {
+ href: function(node, attr) {
+ return Y.DOM.getAttribute(node, attr);
+ }
+ }
+ };
+
+Y.mix(Y.Selector, SelectorCSS2, true);
+Y.Selector.getters.src = Y.Selector.getters.rel = Y.Selector.getters.href;
+
+// IE wants class with native queries
+if (Y.Selector.useNative && document.querySelector) {
+ Y.Selector.shorthand['\\.(-?[_a-z]+[-\\w]*)'] = '[class~=$1]';
+}
+
+
+
+}, '3.0.0' ,{requires:['selector-native']});
+
+
+YUI.add('selector', function(Y){}, '3.0.0' ,{use:['selector-native', 'selector-css2']});
+