All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wings.js.yui.datatable.datatable.js Maven / Gradle / Ivy

/*
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 2.9.0
*/
/**
 * Mechanism to execute a series of callbacks in a non-blocking queue.  Each callback is executed via setTimout unless configured with a negative timeout, in which case it is run in blocking mode in the same execution thread as the previous callback.  Callbacks can be function references or object literals with the following keys:
 * 
    *
  • method - {Function} REQUIRED the callback function.
  • *
  • scope - {Object} the scope from which to execute the callback. Default is the global window scope.
  • *
  • argument - {Array} parameters to be passed to method as individual arguments.
  • *
  • timeout - {number} millisecond delay to wait after previous callback completion before executing this callback. Negative values cause immediate blocking execution. Default 0.
  • *
  • until - {Function} boolean function executed before each iteration. Return true to indicate completion and proceed to the next callback.
  • *
  • iterations - {Number} number of times to execute the callback before proceeding to the next callback in the chain. Incompatible with until.
  • *
* * @namespace YAHOO.util * @class Chain * @constructor * @param callback* {Function|Object} Any number of callbacks to initialize the queue */ YAHOO.util.Chain = function () { /** * The callback queue * @property q * @type {Array} * @private */ this.q = [].slice.call(arguments); /** * Event fired when the callback queue is emptied via execution (not via * a call to chain.stop(). * @event end */ this.createEvent('end'); }; YAHOO.util.Chain.prototype = { /** * Timeout id used to pause or stop execution and indicate the execution state of the Chain. 0 indicates paused or stopped, -1 indicates blocking execution, and any positive number indicates non-blocking execution. * @property id * @type {number} * @private */ id : 0, /** * Begin executing the chain, or resume execution from the last paused position. * @method run * @return {Chain} the Chain instance */ run : function () { // Grab the first callback in the queue var c = this.q[0], fn; // If there is no callback in the queue or the Chain is currently // in an execution mode, return if (!c) { this.fireEvent('end'); return this; } else if (this.id) { return this; } fn = c.method || c; if (typeof fn === 'function') { var o = c.scope || {}, args = c.argument || [], ms = c.timeout || 0, me = this; if (!(args instanceof Array)) { args = [args]; } // Execute immediately if the callback timeout is negative. if (ms < 0) { this.id = ms; if (c.until) { for (;!c.until();) { // Execute the callback from scope, with argument fn.apply(o,args); } } else if (c.iterations) { for (;c.iterations-- > 0;) { fn.apply(o,args); } } else { fn.apply(o,args); } this.q.shift(); this.id = 0; return this.run(); } else { // If the until condition is set, check if we're done if (c.until) { if (c.until()) { // Shift this callback from the queue and execute the next // callback this.q.shift(); return this.run(); } // Otherwise if either iterations is not set or we're // executing the last iteration, shift callback from the queue } else if (!c.iterations || !--c.iterations) { this.q.shift(); } // Otherwise set to execute after the configured timeout this.id = setTimeout(function () { // Execute the callback from scope, with argument fn.apply(o,args); // Check if the Chain was not paused from inside the callback if (me.id) { // Indicate ready to run state me.id = 0; // Start the fun all over again me.run(); } },ms); } } return this; }, /** * Add a callback to the end of the queue * @method add * @param c {Function|Object} the callback function ref or object literal * @return {Chain} the Chain instance */ add : function (c) { this.q.push(c); return this; }, /** * Pause the execution of the Chain after the current execution of the * current callback completes. If called interstitially, clears the * timeout for the pending callback. Paused Chains can be restarted with * chain.run() * @method pause * @return {Chain} the Chain instance */ pause: function () { // Conditional added for Caja compatibility if (this.id > 0) { clearTimeout(this.id); } this.id = 0; return this; }, /** * Stop and clear the Chain's queue after the current execution of the * current callback completes. * @method stop * @return {Chain} the Chain instance */ stop : function () { this.pause(); this.q = []; return this; } }; YAHOO.lang.augmentProto(YAHOO.util.Chain,YAHOO.util.EventProvider); /** * Augments the Event Utility with a delegate method that * facilitates easy creation of delegated event listeners. (Note: Using CSS * selectors as the filtering criteria for delegated event listeners requires * inclusion of the Selector Utility.) * * @module event-delegate * @title Event Utility Event Delegation Module * @namespace YAHOO.util * @requires event */ (function () { var Event = YAHOO.util.Event, Lang = YAHOO.lang, delegates = [], getMatch = function(el, selector, container) { var returnVal; if (!el || el === container) { returnVal = false; } else { returnVal = YAHOO.util.Selector.test(el, selector) ? el: getMatch(el.parentNode, selector, container); } return returnVal; }; Lang.augmentObject(Event, { /** * Creates a delegate function used to call event listeners specified * via the YAHOO.util.Event.delegate method. * * @method _createDelegate * * @param {Function} fn The method (event listener) to call. * @param {Function|string} filter Function or CSS selector used to * determine for what element(s) the event listener should be called. * @param {Object} obj An arbitrary object that will be * passed as a parameter to the listener. * @param {Boolean|object} overrideContext If true, the value of the * obj parameter becomes the execution context * of the listener. If an object, this object * becomes the execution context. * @return {Function} Function that will call the event listener * specified by the YAHOO.util.Event.delegate method. * @private * @for Event * @static */ _createDelegate: function (fn, filter, obj, overrideContext) { return function (event) { var container = this, target = Event.getTarget(event), selector = filter, // The user might have specified the document object // as the delegation container, in which case it is not // nessary to scope the provided CSS selector(s) to the // delegation container bDocument = (container.nodeType === 9), matchedEl, context, sID, sIDSelector; if (Lang.isFunction(filter)) { matchedEl = filter(target); } else if (Lang.isString(filter)) { if (!bDocument) { sID = container.id; if (!sID) { sID = Event.generateId(container); } // Scope all selectors to the container sIDSelector = ("#" + sID + " "); selector = (sIDSelector + filter).replace(/,/gi, ("," + sIDSelector)); } if (YAHOO.util.Selector.test(target, selector)) { matchedEl = target; } else if (YAHOO.util.Selector.test(target, ((selector.replace(/,/gi, " *,")) + " *"))) { // The target is a descendant of an element matching // the selector, so crawl up to find the ancestor that // matches the selector matchedEl = getMatch(target, selector, container); } } if (matchedEl) { // The default context for delegated listeners is the // element that matched the filter. context = matchedEl; if (overrideContext) { if (overrideContext === true) { context = obj; } else { context = overrideContext; } } // Call the listener passing in the container and the // element that matched the filter in case the user // needs those. return fn.call(context, event, matchedEl, container, obj); } }; }, /** * Appends a delegated event listener. Delegated event listeners * receive three arguments by default: the DOM event, the element * specified by the filtering function or CSS selector, and the * container element (the element to which the event listener is * bound). (Note: Using the delegate method requires the event-delegate * module. Using CSS selectors as the filtering criteria for delegated * event listeners requires inclusion of the Selector Utility.) * * @method delegate * * @param {String|HTMLElement|Array|NodeList} container An id, an element * reference, or a collection of ids and/or elements to assign the * listener to. * @param {String} type The type of event listener to append * @param {Function} fn The method the event invokes * @param {Function|string} filter Function or CSS selector used to * determine for what element(s) the event listener should be called. * When a function is specified, the function should return an * HTML element. Using a CSS Selector requires the inclusion of the * CSS Selector Utility. * @param {Object} obj An arbitrary object that will be * passed as a parameter to the listener * @param {Boolean|object} overrideContext If true, the value of the obj parameter becomes * the execution context of the listener. If an * object, this object becomes the execution * context. * @return {Boolean} Returns true if the action was successful or defered, * false if one or more of the elements * could not have the listener attached, * or if the operation throws an exception. * @static * @for Event */ delegate: function (container, type, fn, filter, obj, overrideContext) { var sType = type, fnMouseDelegate, fnDelegate; if (Lang.isString(filter) && !YAHOO.util.Selector) { return false; } if (type == "mouseenter" || type == "mouseleave") { if (!Event._createMouseDelegate) { return false; } // Look up the real event--either mouseover or mouseout sType = Event._getType(type); fnMouseDelegate = Event._createMouseDelegate(fn, obj, overrideContext); fnDelegate = Event._createDelegate(function (event, matchedEl, container) { return fnMouseDelegate.call(matchedEl, event, container); }, filter, obj, overrideContext); } else { fnDelegate = Event._createDelegate(fn, filter, obj, overrideContext); } delegates.push([container, sType, fn, fnDelegate]); return Event.on(container, sType, fnDelegate); }, /** * Removes a delegated event listener. * * @method removeDelegate * * @param {String|HTMLElement|Array|NodeList} container An id, an element * reference, or a collection of ids and/or elements to remove * the listener from. * @param {String} type The type of event to remove. * @param {Function} fn The method the event invokes. If fn is * undefined, then all event listeners for the type of event are * removed. * @return {boolean} Returns true if the unbind was successful, false * otherwise. * @static * @for Event */ removeDelegate: function (container, type, fn) { var sType = type, returnVal = false, index, cacheItem; // Look up the real event--either mouseover or mouseout if (type == "mouseenter" || type == "mouseleave") { sType = Event._getType(type); } index = Event._getCacheIndex(delegates, container, sType, fn); if (index >= 0) { cacheItem = delegates[index]; } if (container && cacheItem) { returnVal = Event.removeListener(cacheItem[0], cacheItem[1], cacheItem[3]); if (returnVal) { delete delegates[index][2]; delete delegates[index][3]; delegates.splice(index, 1); } } return returnVal; } }); }()); /** * Augments the Event Utility with support for the mouseenter and mouseleave * events: A mouseenter event fires the first time the mouse enters an * element; a mouseleave event first the first time the mouse leaves an * element. * * @module event-mouseenter * @title Event Utility mouseenter and mouseout Module * @namespace YAHOO.util * @requires event */ (function () { var Event = YAHOO.util.Event, Lang = YAHOO.lang, addListener = Event.addListener, removeListener = Event.removeListener, getListeners = Event.getListeners, delegates = [], specialTypes = { mouseenter: "mouseover", mouseleave: "mouseout" }, remove = function(el, type, fn) { var index = Event._getCacheIndex(delegates, el, type, fn), cacheItem, returnVal; if (index >= 0) { cacheItem = delegates[index]; } if (el && cacheItem) { // removeListener will translate the value of type returnVal = removeListener.call(Event, cacheItem[0], type, cacheItem[3]); if (returnVal) { delete delegates[index][2]; delete delegates[index][3]; delegates.splice(index, 1); } } return returnVal; }; Lang.augmentObject(Event._specialTypes, specialTypes); Lang.augmentObject(Event, { /** * Creates a delegate function used to call mouseover and mouseleave * event listeners specified via the * YAHOO.util.Event.addListener * or YAHOO.util.Event.on method. * * @method _createMouseDelegate * * @param {Function} fn The method (event listener) to call * @param {Object} obj An arbitrary object that will be * passed as a parameter to the listener * @param {Boolean|object} overrideContext If true, the value of the * obj parameter becomes the execution context * of the listener. If an object, this object * becomes the execution context. * @return {Function} Function that will call the event listener * specified by either the YAHOO.util.Event.addListener * or YAHOO.util.Event.on method. * @private * @static * @for Event */ _createMouseDelegate: function (fn, obj, overrideContext) { return function (event, container) { var el = this, relatedTarget = Event.getRelatedTarget(event), context, args; if (el != relatedTarget && !YAHOO.util.Dom.isAncestor(el, relatedTarget)) { context = el; if (overrideContext) { if (overrideContext === true) { context = obj; } else { context = overrideContext; } } // The default args passed back to a mouseenter or // mouseleave listener are: the event, and any object // the user passed when subscribing args = [event, obj]; // Add the element and delegation container as arguments // when delegating mouseenter and mouseleave if (container) { args.splice(1, 0, el, container); } return fn.apply(context, args); } }; }, addListener: function (el, type, fn, obj, overrideContext) { var fnDelegate, returnVal; if (specialTypes[type]) { fnDelegate = Event._createMouseDelegate(fn, obj, overrideContext); fnDelegate.mouseDelegate = true; delegates.push([el, type, fn, fnDelegate]); // addListener will translate the value of type returnVal = addListener.call(Event, el, type, fnDelegate); } else { returnVal = addListener.apply(Event, arguments); } return returnVal; }, removeListener: function (el, type, fn) { var returnVal; if (specialTypes[type]) { returnVal = remove.apply(Event, arguments); } else { returnVal = removeListener.apply(Event, arguments); } return returnVal; }, getListeners: function (el, type) { // If the user specified the type as mouseover or mouseout, // need to filter out those used by mouseenter and mouseleave. // If the user specified the type as mouseenter or mouseleave, // need to filter out the true mouseover and mouseout listeners. var listeners = [], elListeners, bMouseOverOrOut = (type === "mouseover" || type === "mouseout"), bMouseDelegate, i, l; if (type && (bMouseOverOrOut || specialTypes[type])) { elListeners = getListeners.call(Event, el, this._getType(type)); if (elListeners) { for (i=elListeners.length-1; i>-1; i--) { l = elListeners[i]; bMouseDelegate = l.fn.mouseDelegate; if ((specialTypes[type] && bMouseDelegate) || (bMouseOverOrOut && !bMouseDelegate)) { listeners.push(l); } } } } else { listeners = getListeners.apply(Event, arguments); } return (listeners && listeners.length) ? listeners : null; } }, true); Event.on = Event.addListener; }()); YAHOO.register("event-mouseenter", YAHOO.util.Event, {version: "2.9.0", build: "2800"}); var Y = YAHOO, Y_DOM = YAHOO.util.Dom, EMPTY_ARRAY = [], Y_UA = Y.env.ua, Y_Lang = Y.lang, Y_DOC = document, Y_DOCUMENT_ELEMENT = Y_DOC.documentElement, Y_DOM_inDoc = Y_DOM.inDocument, Y_mix = Y_Lang.augmentObject, Y_guid = Y_DOM.generateId, Y_getDoc = function(element) { var doc = Y_DOC; if (element) { doc = (element.nodeType === 9) ? element : // element === document element.ownerDocument || // element === DOM node element.document || // element === window Y_DOC; // default } return doc; }, Y_Array = function(o, startIdx) { var l, a, start = startIdx || 0; // IE errors when trying to slice HTMLElement collections try { return Array.prototype.slice.call(o, start); } catch (e) { a = []; l = o.length; for (; start < l; start++) { a.push(o[start]); } return a; } }, Y_DOM_allById = function(id, root) { root = root || Y_DOC; var nodes = [], ret = [], i, node; if (root.querySelectorAll) { ret = root.querySelectorAll('[id="' + id + '"]'); } else if (root.all) { nodes = root.all(id); if (nodes) { // root.all may return HTMLElement or HTMLCollection. // some elements are also HTMLCollection (FORM, SELECT). if (nodes.nodeName) { if (nodes.id === id) { // avoid false positive on name ret.push(nodes); nodes = EMPTY_ARRAY; // done, no need to filter } else { // prep for filtering nodes = [nodes]; } } if (nodes.length) { // filter out matches on node.name // and element.id as reference to element with id === 'id' for (i = 0; node = nodes[i++];) { if (node.id === id || (node.attributes && node.attributes.id && node.attributes.id.value === id)) { ret.push(node); } } } } } else { ret = [Y_getDoc(root).getElementById(id)]; } return ret; }; /** * 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 */ var COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition', OWNER_DOCUMENT = 'ownerDocument', Selector = { _foundCache: [], useNative: true, _compare: ('sourceIndex' in Y_DOCUMENT_ELEMENT) ? function(nodeA, nodeB) { var a = nodeA.sourceIndex, b = nodeB.sourceIndex; if (a === b) { return 0; } else if (a > b) { return 1; } return -1; } : (Y_DOCUMENT_ELEMENT[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) { if (typeof root == 'string') { root = Y_DOM.get(root); if (!root) { return (firstOnly) ? null : []; } } else { root = root || Y_DOC; } var ret = [], useNative = (Selector.useNative && Y_DOC.querySelector && !skipNative), queries = [[selector, root]], query, result, i, fn = (useNative) ? Selector._nativeQuery : 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)); } } Y.log('query: ' + selector + ' returning: ' + ret.length, 'info', 'Selector'); 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 = '[id="' + 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) { if (Y_UA.webkit && selector.indexOf(':checked') > -1 && (Selector.pseudos && Selector.pseudos.checked)) { // webkit (chrome, safari) fails to find "selected" return Selector.query(selector, root, one, true); // redo with skipNative true to try brute query } try { //Y.log('trying native query with: ' + selector, 'info', 'selector-native'); return root['querySelector' + (one ? '' : 'All')](selector); } catch(e) { // fallback to brute if available //Y.log('native query error; reverting to brute query with: ' + selector, 'info', 'selector-native'); return 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 (Selector.test(node, selector)) { ret[ret.length] = node; } } } else { Y.log('invalid filter input (nodes: ' + nodes + ', selector: ' + selector + ')', 'warn', 'Selector'); } return ret; }, test: function(node, selector, root) { var ret = false, groups = selector.split(','), useFrag = false, parent, item, items, frag, i, j, group; if (node && node.tagName) { // only test HTMLElements // we need a root if off-doc if (!root && !Y_DOM_inDoc(node)) { parent = node.parentNode; if (parent) { root = parent; } else { // only use frag when no parent to query frag = node[OWNER_DOCUMENT].createDocumentFragment(); frag.appendChild(node); root = frag; useFrag = true; } } root = root || node[OWNER_DOCUMENT]; if (!node.id) { node.id = Y_guid(); } for (i = 0; (group = groups[i++]);) { // TODO: off-dom test group += '[id="' + node.id + '"]'; items = Selector.query(group, root); for (j = 0; item = items[j++];) { if (item === node) { ret = true; break; } } if (ret) { break; } } if (useFrag) { // cleanup frag.removeChild(node); } } return ret; } }; YAHOO.util.Selector = Selector; /** * 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', SelectorCSS2 = { _reRegExpTokens: /([\^\$\?\[\]\*\+\-\.\(\)\|\\])/, // TODO: move? 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 || []; }, _re: { //attr: /(\[.*\])/g, attr: /(\[[^\]]*\])/g, //esc: /\\[:\[][\w\d\]]*/gi, esc: /\\[:\[\]\(\)#\.\'\>+~"]/gi, //pseudos: /:([\-\w]+(?:\(?:['"]?(.+)['"]?\))*)/i pseudos: /(\([^\)]*\))/g }, /** * Mapping of shorthand tokens to corresponding attribute selector * @property shorthand * @type object */ shorthand: { //'\\#([^\\s\\\\(\\[:]*)': '[id=$1]', '\\#(-?[_a-z]+[-\\w\\uE000]*)': '[id=$1]', //'\\#([^\\s\\\.:\\[\\]]*)': '[id=$1]', //'\\.([^\\s\\\\(\\[:]*)': '[className=$1]' '\\.(-?[_a-z]+[-\\w\\uE000]*)': '[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 !!node.getAttribute(attr); }, // Just test for existence of attribute //'': '.+', //'=': '^{val}$', // equality '~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited '|=': '^{val}(?:-|$)' // optional hyphen-delimited }, pseudos: { 'first-child': function(node) { return 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_getDoc(root), child, 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 || '*'; if (root.getElementsByTagName) { // non-IE lacks DOM api on doc frags // try ID first, unless no root.all && root not in document // (root.all works off document, but not getElementById) // TODO: move to allById? if (id && (root.all || (root.nodeType === 9 || Y_DOM_inDoc(root)))) { nodes = Y_DOM_allById(id, root); // try className } else if (className) { nodes = root.getElementsByClassName(className); } else { // default to tagName nodes = root.getElementsByTagName(tagName); } } else { // brute getElementsByTagName('*') child = root.firstChild; while (child) { if (child.tagName) { // only collect HTMLElements nodes.push(child); } child = child.nextSilbing || child.firstChild; } } 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 = 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 (typeof operator !== 'string' && // protect against String.test monkey-patch (Moo) operator.test && !operator.test(value)) || // regex test (!operator.test && // protect against RegExp as function (webkit) typeof operator === 'function' && !operator(tmpNode, test[0], test[2]))) { // 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; }, combinators: { ' ': { axis: 'parentNode' }, '>': { axis: 'parentNode', direct: true }, '+': { axis: 'previousSibling', direct: true } }, _parsers: [ { name: ATTRIBUTES, //re: /^\[(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i, re: /^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i, fn: function(match, token) { var operator = match[2] || '', operators = Selector.operators, escVal = (match[3]) ? match[3].replace(/\\/g, '') : '', test; // add prefiltering for ID and CLASS if ((match[1] === 'id' && operator === '=') || (match[1] === 'className' && Y_DOCUMENT_ELEMENT.getElementsByClassName && (operator === '~=' || operator === '='))) { token.prefilter = match[1]; match[3] = escVal; // escape all but ID for prefilter, which may run through QSA (via Dom.allById) token[match[1]] = (match[1] === 'id') ? match[3] : escVal; } // add tests if (operator in operators) { test = operators[operator]; if (typeof test === 'string') { match[3] = escVal.replace(Selector._reRegExpTokens, '\\$1'); test = new RegExp(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]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i, fn: function(match, token) { var test = Selector[PSEUDOS][match[1]]; if (test) { // reorder match array and unescape special chars for tests if (match[2]) { match[2] = match[2].replace(/\\/g, ''); } 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.name !== 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 = Selector.combinators[match[1]]; } } found = true; } } } while (found && selector.length); if (!found || selector.length) { // not fully parsed Y.log('query: ' + query + ' contains unsupported token in: ' + selector, 'warn', 'Selector'); tokens = []; } return tokens; }, _replaceShorthand: function(selector) { var shorthand = Selector.shorthand, esc = selector.match(Selector._re.esc), // pull escaped colon, brackets, etc. attrs, pseudos, re, i, len; if (esc) { selector = selector.replace(Selector._re.esc, '\uE000'); } attrs = selector.match(Selector._re.attr); pseudos = selector.match(Selector._re.pseudos); if (attrs) { selector = selector.replace(Selector._re.attr, '\uE001'); } if (pseudos) { selector = selector.replace(Selector._re.pseudos, '\uE002'); } for (re in shorthand) { if (shorthand.hasOwnProperty(re)) { selector = selector.replace(new RegExp(re, 'gi'), shorthand[re]); } } if (attrs) { for (i = 0, len = attrs.length; i < len; ++i) { selector = selector.replace(/\uE001/, attrs[i]); } } if (pseudos) { for (i = 0, len = pseudos.length; i < len; ++i) { selector = selector.replace(/\uE002/, pseudos[i]); } } selector = selector.replace(/\[/g, '\uE003'); selector = selector.replace(/\]/g, '\uE004'); selector = selector.replace(/\(/g, '\uE005'); selector = selector.replace(/\)/g, '\uE006'); if (esc) { for (i = 0, len = esc.length; i < len; ++i) { selector = selector.replace('\uE000', esc[i]); } } return selector; }, _attrFilters: { 'class': 'className', 'for': 'htmlFor' }, getters: { href: function(node, attr) { return Y_DOM.getAttribute(node, attr); } } }; Y_mix(Selector, SelectorCSS2, true); Selector.getters.src = Selector.getters.rel = Selector.getters.href; // IE wants class with native queries if (Selector.useNative && Y_DOC.querySelector) { Selector.shorthand['\\.([^\\s\\\\(\\[:]*)'] = '[class~=$1]'; } /** * The selector css3 module provides support for css3 selectors. * @module dom * @submodule selector-css3 * @for Selector */ /* 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 */ Selector._reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/; Selector._getNth = function(node, expr, tag, reverse) { Selector._reNth.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 = [], siblings = Selector._children(node.parentNode, tag), op; 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; }; Y_mix(Selector.pseudos, { 'root': function(node) { return node === node.ownerDocument.documentElement; }, 'nth-child': function(node, expr) { return Selector._getNth(node, expr); }, 'nth-last-child': function(node, expr) { return Selector._getNth(node, expr, null, true); }, 'nth-of-type': function(node, expr) { return Selector._getNth(node, expr, node.tagName); }, 'nth-last-of-type': function(node, expr) { return Selector._getNth(node, expr, node.tagName, true); }, 'last-child': function(node) { var children = Selector._children(node.parentNode); return children[children.length - 1] === node; }, 'first-of-type': function(node) { return Selector._children(node.parentNode, node.tagName)[0] === node; }, 'last-of-type': function(node) { var children = Selector._children(node.parentNode, node.tagName); return children[children.length - 1] === node; }, 'only-child': function(node) { var children = Selector._children(node.parentNode); return children.length === 1 && children[0] === node; }, 'only-of-type': function(node) { var children = Selector._children(node.parentNode, node.tagName); return children.length === 1 && children[0] === node; }, 'empty': function(node) { return node.childNodes.length === 0; }, 'not': function(node, expr) { return !Selector.test(node, expr); }, 'contains': function(node, expr) { var text = node.innerText || node.textContent || ''; return text.indexOf(expr) > -1; }, 'checked': function(node) { return (node.checked === true || node.selected === true); }, enabled: function(node) { return (node.disabled !== undefined && !node.disabled); }, disabled: function(node) { return (node.disabled); } }); Y_mix(Selector.operators, { '^=': '^{val}', // Match starts with value '!=': function(node, attr, val) { return node[attr] !== val; }, // Match starts with value '$=': '{val}$', // Match ends with value '*=': '{val}' // Match contains value as substring }); Selector.combinators['~'] = { axis: 'previousSibling' }; YAHOO.register("selector", YAHOO.util.Selector, {version: "2.9.0", build: "2800"}); /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ var Dom = YAHOO.util.Dom; /** * The ColumnSet class defines and manages a DataTable's Columns, * including nested hierarchies and access to individual Column instances. * * @namespace YAHOO.widget * @class ColumnSet * @uses YAHOO.util.EventProvider * @constructor * @param aDefinitions {Object[]} Array of object literals that define cells in * the THEAD. */ YAHOO.widget.ColumnSet = function(aDefinitions) { this._sId = Dom.generateId(null, "yui-cs"); // "yui-cs" + YAHOO.widget.ColumnSet._nCount; // First clone the defs aDefinitions = YAHOO.widget.DataTable._cloneObject(aDefinitions); this._init(aDefinitions); YAHOO.widget.ColumnSet._nCount++; }; ///////////////////////////////////////////////////////////////////////////// // // Private member variables // ///////////////////////////////////////////////////////////////////////////// /** * Internal class variable to index multiple ColumnSet instances. * * @property ColumnSet._nCount * @type Number * @private * @static */ YAHOO.widget.ColumnSet._nCount = 0; YAHOO.widget.ColumnSet.prototype = { /** * Unique instance name. * * @property _sId * @type String * @private */ _sId : null, /** * Array of object literal Column definitions passed to the constructor. * * @property _aDefinitions * @type Object[] * @private */ _aDefinitions : null, ///////////////////////////////////////////////////////////////////////////// // // Public member variables // ///////////////////////////////////////////////////////////////////////////// /** * Top-down tree representation of Column hierarchy. * * @property tree * @type YAHOO.widget.Column[] */ tree : null, /** * Flattened representation of all Columns. * * @property flat * @type YAHOO.widget.Column[] * @default [] */ flat : null, /** * Array of Columns that map one-to-one to a table column. * * @property keys * @type YAHOO.widget.Column[] * @default [] */ keys : null, /** * ID index of nested parent hierarchies for HEADERS accessibility attribute. * * @property headers * @type String[] * @default [] */ headers : null, ///////////////////////////////////////////////////////////////////////////// // // Private methods // ///////////////////////////////////////////////////////////////////////////// /** * Initializes ColumnSet instance with data from Column definitions. * * @method _init * @param aDefinitions {Object[]} Array of object literals that define cells in * the THEAD . * @private */ _init : function(aDefinitions) { // DOM tree representation of all Columns var tree = []; // Flat representation of all Columns var flat = []; // Flat representation of only Columns that are meant to display data var keys = []; // Array of HEADERS attribute values for all keys in the "keys" array var headers = []; // Tracks current node list depth being tracked var nodeDepth = -1; // Internal recursive function to define Column instances var parseColumns = function(nodeList, parent) { // One level down nodeDepth++; // Create corresponding tree node if not already there for this depth if(!tree[nodeDepth]) { tree[nodeDepth] = []; } // Parse each node at this depth for attributes and any children for(var j=0; j maxRowDepth) { maxRowDepth = tmpRowDepth; } } } }; // Count max row depth for each row for(var m=0; m-1; i--) { if(allColumns[i]._sId === column) { return allColumns[i]; } } } return null; }, /** * Returns Column instance with given key or ColumnSet key index. * * @method getColumn * @param column {String | Number} Column key or ColumnSet key index. * @return {YAHOO.widget.Column} Column instance. */ getColumn : function(column) { if(YAHOO.lang.isNumber(column) && this.keys[column]) { return this.keys[column]; } else if(YAHOO.lang.isString(column)) { var allColumns = this.flat; var aColumns = []; for(var i=0; i 1) { return aColumns; } } return null; }, /** * Public accessor returns array of given Column's desendants (if any), including itself. * * @method getDescendants * @parem {YAHOO.widget.Column} Column instance. * @return {Array} Array including the Column itself and all descendants (if any). */ getDescendants : function(oColumn) { var oSelf = this; var allDescendants = []; var i; // Recursive function to loop thru all children var parse = function(oParent) { allDescendants.push(oParent); // This Column has children if(oParent.children) { for(i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy