node-debug.js revision 9fca169e8847cdfcd3016985a4f01b5ee3c89f40
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncYUI.add('node-base', function(Y) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @module node
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @submodule node-base
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
78f327ee942771169c65c91baf789fd10e72b01avboxsync/**
78f327ee942771169c65c91baf789fd10e72b01avboxsync * The Node class provides a wrapper for manipulating DOM Nodes.
78f327ee942771169c65c91baf789fd10e72b01avboxsync * Node properties can be accessed via the set/get methods.
78f327ee942771169c65c91baf789fd10e72b01avboxsync * Use Y.get() to retrieve Node instances.
78f327ee942771169c65c91baf789fd10e72b01avboxsync *
78f327ee942771169c65c91baf789fd10e72b01avboxsync * <strong>NOTE:</strong> Node properties are accessed using
78f327ee942771169c65c91baf789fd10e72b01avboxsync * the <code>set</code> and <code>get</code> methods.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @class Node
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @constructor
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @for Node
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync// "globals"
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsyncvar g_nodes = {},
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync g_nodelists = {},
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync g_restrict = {},
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync g_slice = Array.prototype.slice,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync DOT = '.',
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync NODE_NAME = 'nodeName',
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync NODE_TYPE = 'nodeType',
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync OWNER_DOCUMENT = 'ownerDocument',
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync TAG_NAME = 'tagName',
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync UID = '_yuid',
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Node = function(node, restricted) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync var config = null;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync this[UID] = Y.stamp(node);
0912cf29d2641459d225c40114c567a63273746cvboxsync if (!this[UID]) { // stamp failed; likely IE non-HTMLElement
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync this[UID] = Y.guid();
0912cf29d2641459d225c40114c567a63273746cvboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
701a45600245e42829e1187817299e812eebdec5vboxsync g_nodes[this[UID]] = node;
0912cf29d2641459d225c40114c567a63273746cvboxsync Node._instances[this[UID]] = this;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (restricted) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync g_restrict[this[UID]] = true;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync this.addAttrs(Node.ATTRS);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync this._initPlugins();
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync },
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync // used with previous/next/ancestor tests
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync _wrapFn = function(fn) {
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync var ret = null;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (fn) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ret = (typeof fn === 'string') ?
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync function(n) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Y.Selector.test(n, fn);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } :
0912cf29d2641459d225c40114c567a63273746cvboxsync function(n) {
0912cf29d2641459d225c40114c567a63273746cvboxsync return fn(Node.get(n));
0912cf29d2641459d225c40114c567a63273746cvboxsync };
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync return ret;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync };
0912cf29d2641459d225c40114c567a63273746cvboxsync// end "globals"
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.NAME = 'Node';
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.re_aria = /^(?:role$|aria-)/;
0912cf29d2641459d225c40114c567a63273746cvboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.DOM_EVENTS = {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync abort: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync blur: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync change: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync click: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync close: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync command: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync contextmenu: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync drag: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync dragstart: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync dragenter: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync dragover: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync dragleave: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync dragend: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync drop: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync dblclick: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync error: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync focus: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync keydown: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync keypress: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync keyup: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync load: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync mousedown: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync mousemove: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync mouseout: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync mouseover: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync mouseup: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync mousemultiwheel: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync mousewheel: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync submit: true,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync mouseenter: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync mouseleave: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync scroll: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync reset: true,
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync resize: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync select: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync textInput: true,
0912cf29d2641459d225c40114c567a63273746cvboxsync unload: true
0912cf29d2641459d225c40114c567a63273746cvboxsync};
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync// Add custom event adaptors to this list. This will make it so
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync// that delegate, key, available, contentready, etc all will
0912cf29d2641459d225c40114c567a63273746cvboxsync// be available through Node.on
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncY.mix(Node.DOM_EVENTS, Y.Env.evt.plugins);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode._instances = {};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Registers plugins to be instantiated at the class level (plugins
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * which should be plugged into every instance of Node by default).
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method Node.plug
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @static
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.plug = function() {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync var args = g_slice.call(arguments, 0);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync args.unshift(Node);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Y.Plugin.Host.plug.apply(Y.Base, args);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Node;
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync/**
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync * Unregisters any class level plugins which have been registered by the Node
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method Node.unplug
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync * @static
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync *
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync * @param {Function | Array} plugin The plugin class, or an array of plugin classes
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsyncNode.unplug = function() {
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync var args = g_slice.call(arguments, 0);
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync args.unshift(Node);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync Y.Plugin.Host.unplug.apply(Y.Base, args);
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync return Node;
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync};
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync
c16bfd344d242a6352ec72b4478099ccadfc5a70vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Retrieves the DOM node bound to a Node instance
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method Node.getDOMNode
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @static
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {Y.Node || HTMLNode} node The Node instance or an HTMLNode
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @return {HTMLNode} The DOM node bound to the Node instance. If a DOM node is passed
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * as the node argument, it is simply returned.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.getDOMNode = function(node) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (node) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (node instanceof Node) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync node = g_nodes[node[UID]];
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else if (!node[NODE_NAME] || Y.DOM.isWindow(node)) { // must already be a DOMNode
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync node = null;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return node || null;
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync};
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsyncNode.scrubVal = function(val, node, depth) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (node && val) { // only truthy values are risky
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (typeof val === 'object' || typeof val === 'function') { // safari nodeList === function
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (NODE_TYPE in val || Y.DOM.isWindow(val)) {// node || window
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (g_restrict[node[UID]] && !node.contains(val)) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync val = null; // not allowed to go outside of root node
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync val = Node.get(val);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else if (val.item || // dom collection or Node instance // TODO: check each node for restrict? block ancestor?
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync val = Y.all(val);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync depth = (depth === undefined) ? 4 : depth;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (depth > 0) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync for (var i in val) { // TODO: test this and pull hasOwnProperty check if safe?
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (val.hasOwnProperty && val.hasOwnProperty(i)) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync val[i] = Node.scrubVal(val[i], node, --depth);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync }
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync } else if (val === undefined) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync val = node; // for chaining
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return val;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync};
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.addMethod = function(name, fn, context) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (name && fn && typeof fn === 'function') {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Node.prototype[name] = function() {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync context = context || this;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync var args = g_slice.call(arguments),
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ret;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync if (args[0] && args[0] instanceof Node) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync args[0] = Node.getDOMNode(args[0]);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (args[1] && args[1] instanceof Node) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync args[1] = Node.getDOMNode(args[1]);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync }
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync args.unshift(g_nodes[this[UID]]);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ret = Node.scrubVal(fn.apply(context, args), this);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return ret;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync };
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Y.log('unable to add method: ' + name, 'warn', 'Node');
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.importMethod = function(host, name, altName) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (typeof name === 'string') {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync altName = altName || name;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Node.addMethod(altName, host[name], host);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Y.each(name, function(n) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Node.importMethod(host, n);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync });
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Returns a single Node instance bound to the node or the
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * first element matching the given selector.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method Y.get
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @static
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {String | HTMLElement} node a node or Selector
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {Y.Node || HTMLElement} doc an optional document to scan. Defaults to Y.config.doc.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {Boolean} restrict Whether or not the Node instance should be restricted to accessing
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * its subtree only.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.get = function(node, doc, restrict) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync var instance = null;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (typeof node === 'string') {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (node.indexOf('doc') === 0) { // doc OR document
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync node = Y.config.doc;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else if (node.indexOf('win') === 0) { // doc OR document
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync node = Y.config.win;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync node = Y.Selector.query(node, doc, true);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (node) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync instance = Node._instances[node[UID]]; // reuse exising instances
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (!instance) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync instance = new Node(node, restrict);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else if (restrict) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync g_restrict[instance[UID]] = true;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync // TODO: restrict on subsequent call?
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return instance;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Creates a new dom node using the provided markup string.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method create
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @static
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {String} html The markup used to create the element
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {HTMLDocument} doc An optional document context
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.create = function() {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Node.get(Y.DOM.create.apply(Y.DOM, arguments));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.ATTRS = {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Allows for getting and setting the text of an element.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Formatting is preserved and special characters are treated literally.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @config text
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @type String
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync text: {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync getter: function() {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Y.DOM.getText(g_nodes[this[UID]]);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync setter: function(content) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Y.DOM.setText(g_nodes[this[UID]], content);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return content;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync 'options': {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync getter: function() {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return this.getElementsByTagName('option');
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Returns a NodeList instance of all HTMLElement children.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @readOnly
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync * @config children
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync * @type NodeList
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync 'children': {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync getter: function() {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync var node = g_nodes[this[UID]],
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync children = node.children,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync childNodes, i, len;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (!children) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync childNodes = node.childNodes;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync children = [];
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync for (i = 0, len = childNodes.length; i < len; ++i) {
0912cf29d2641459d225c40114c567a63273746cvboxsync if (childNodes[i][TAG_NAME]) {
0912cf29d2641459d225c40114c567a63273746cvboxsync children[children.length] = childNodes[i];
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Y.all(children);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync value: {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync getter: function() {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Y.DOM.getValue(g_nodes[this[UID]]);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync setter: function(val) {
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync Y.DOM.setValue(g_nodes[this[UID]], val);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return val;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
0912cf29d2641459d225c40114c567a63273746cvboxsync
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync/*
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync style: {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync getter: function(attr) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Y.DOM.getStyle(g_nodes[this[UID]].style, attr);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync*/
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync};
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync// call with instance context
230bd8589bba39933ac5ec21482d6186d675e604vboxsyncNode.DEFAULT_SETTER = function(name, val) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync var node = g_nodes[this[UID]],
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync strPath;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync if (name.indexOf(DOT) > -1) {
0912cf29d2641459d225c40114c567a63273746cvboxsync strPath = name;
0912cf29d2641459d225c40114c567a63273746cvboxsync name = name.split(DOT);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Y.Object.setValue(node, name, val);
0912cf29d2641459d225c40114c567a63273746cvboxsync } else if (node[name] !== undefined) { // only set DOM attributes
0912cf29d2641459d225c40114c567a63273746cvboxsync node[name] = val;
0912cf29d2641459d225c40114c567a63273746cvboxsync }
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync return val;
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync};
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync// call with instance context
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncNode.DEFAULT_GETTER = function(name) {
0912cf29d2641459d225c40114c567a63273746cvboxsync var node = g_nodes[this[UID]],
0912cf29d2641459d225c40114c567a63273746cvboxsync val;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync if (name.indexOf && name.indexOf(DOT) > -1) {
0912cf29d2641459d225c40114c567a63273746cvboxsync val = Y.Object.getValue(node, name.split(DOT));
0912cf29d2641459d225c40114c567a63273746cvboxsync } else {
0912cf29d2641459d225c40114c567a63273746cvboxsync val = node[name];
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync return val ? Y.Node.scrubVal(val, this) : val;
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync};
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsyncNode.getters = {
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync};
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsyncY.augment(Node, Y.Event.Target);
0912cf29d2641459d225c40114c567a63273746cvboxsyncY.augment(Node, Y.Plugin.Host);
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsyncY.mix(Node.prototype, {
0912cf29d2641459d225c40114c567a63273746cvboxsync _getClasses: function() {
0912cf29d2641459d225c40114c567a63273746cvboxsync return [Node];
0912cf29d2641459d225c40114c567a63273746cvboxsync },
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync toString: function() {
0912cf29d2641459d225c40114c567a63273746cvboxsync var str = '',
0912cf29d2641459d225c40114c567a63273746cvboxsync errorMsg = this[UID] + ': not bound to a node',
0912cf29d2641459d225c40114c567a63273746cvboxsync node = g_nodes[this[UID]];
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync if (node) {
0912cf29d2641459d225c40114c567a63273746cvboxsync str += node[NODE_NAME];
0912cf29d2641459d225c40114c567a63273746cvboxsync if (node.id) {
0912cf29d2641459d225c40114c567a63273746cvboxsync str += '#' + node.id;
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync if (node.className) {
0912cf29d2641459d225c40114c567a63273746cvboxsync str += '.' + node.className.replace(' ', '.');
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync // TODO: add yuid?
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync str += ' ' + this[UID];
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync return str || errorMsg;
0912cf29d2641459d225c40114c567a63273746cvboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync addAttrs: function(hash) {
0912cf29d2641459d225c40114c567a63273746cvboxsync this._attrs = this._attrs || {};
0912cf29d2641459d225c40114c567a63273746cvboxsync Y.each(hash, function(config, attr) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync this._attrs[attr] = config;
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync }, this);
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync },
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync get: function(attr) {
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync var attrConfig = this._attrs[attr],
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync val;
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync if (attrConfig && attrConfig.getter) {
0912cf29d2641459d225c40114c567a63273746cvboxsync val = attrConfig.getter.call(this);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else if (Node.re_aria.test(attr)) {
0912cf29d2641459d225c40114c567a63273746cvboxsync val = Y.Node.getDOMNode(this).getAttribute(attr, 2);
0912cf29d2641459d225c40114c567a63273746cvboxsync } else {
0912cf29d2641459d225c40114c567a63273746cvboxsync val = Node.DEFAULT_GETTER.apply(this, arguments);
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync return val;
0912cf29d2641459d225c40114c567a63273746cvboxsync },
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync set: function(attr, val) {
0912cf29d2641459d225c40114c567a63273746cvboxsync var attrConfig = this._attrs[attr],
0912cf29d2641459d225c40114c567a63273746cvboxsync val;
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync if (attrConfig && attrConfig.setter) {
0912cf29d2641459d225c40114c567a63273746cvboxsync attrConfig.setter.call(this, val);
0912cf29d2641459d225c40114c567a63273746cvboxsync } else if (Node.re_aria.test(attr)) {
0912cf29d2641459d225c40114c567a63273746cvboxsync Y.Node.getDOMNode(this).setAttribute(attr, val);
0912cf29d2641459d225c40114c567a63273746cvboxsync } else {
0912cf29d2641459d225c40114c567a63273746cvboxsync Node.DEFAULT_SETTER.apply(this, arguments);
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync return this;
0912cf29d2641459d225c40114c567a63273746cvboxsync },
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /**
0912cf29d2641459d225c40114c567a63273746cvboxsync * Creates a new Node using the provided markup string.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @method create
0912cf29d2641459d225c40114c567a63273746cvboxsync * @param {String} html The markup used to create the element
0912cf29d2641459d225c40114c567a63273746cvboxsync * @param {HTMLDocument} doc An optional document context
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
0912cf29d2641459d225c40114c567a63273746cvboxsync create: Node.create,
0912cf29d2641459d225c40114c567a63273746cvboxsync
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync /**
0912cf29d2641459d225c40114c567a63273746cvboxsync * Compares nodes to determine if they match.
0912cf29d2641459d225c40114c567a63273746cvboxsync * Node instances can be compared to each other and/or HTMLElements.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @method compareTo
0912cf29d2641459d225c40114c567a63273746cvboxsync * @param {HTMLElement | Node} refNode The reference node to compare to the node.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @return {Boolean} True if the nodes match, false if they do not.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
0912cf29d2641459d225c40114c567a63273746cvboxsync compareTo: function(refNode) {
0912cf29d2641459d225c40114c567a63273746cvboxsync var node = g_nodes[this[UID]];
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (refNode instanceof Y.Node) {
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync refNode = Y.Node.getDOMNode(refNode);
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync return node === refNode;
0912cf29d2641459d225c40114c567a63273746cvboxsync },
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /**
0912cf29d2641459d225c40114c567a63273746cvboxsync * Determines whether the node is appended to the document.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @method inDoc
0912cf29d2641459d225c40114c567a63273746cvboxsync * @param {Node|HTMLElement} doc optional An optional document to check against.
0912cf29d2641459d225c40114c567a63273746cvboxsync * Defaults to current document.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @return {Boolean} Whether or not this node is appended to the document.
0912cf29d2641459d225c40114c567a63273746cvboxsync */
0912cf29d2641459d225c40114c567a63273746cvboxsync inDoc: function(doc) {
0912cf29d2641459d225c40114c567a63273746cvboxsync var node = g_nodes[this[UID]];
0912cf29d2641459d225c40114c567a63273746cvboxsync doc = (doc) ? Node.getDOMNode(doc) : node[OWNER_DOCUMENT];
0912cf29d2641459d225c40114c567a63273746cvboxsync if (doc.documentElement) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Y.DOM.contains(doc.documentElement, node);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync getById: function(id) {
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync var node = g_nodes[this[UID]],
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ret = Y.DOM.byId(id, node[OWNER_DOCUMENT]);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (ret && Y.DOM.contains(node, ret)) {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync ret = Y.get(ret);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync } else {
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync ret = null;
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync }
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync return ret;
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync /**
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync * Returns the nearest ancestor that passes the test applied by supplied boolean method.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method ancestor
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync * @param {String | Function} fn A selector or boolean method for testing elements.
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync * If a function is used, it receives the current node being tested as the only argument.
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync * @return {Node} The matching Node instance or null if not found
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync */
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync ancestor: function(fn) {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync return Node.get(Y.DOM.elementByAxis(g_nodes[this[UID]], 'parentNode', _wrapFn(fn)));
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
ab559f6b837e1c2db227f159deb13f1c0d6365bfvboxsync /**
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync * Returns the previous matching sibling.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Returns the nearest element node sibling if no method provided.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method previous
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {String | Function} fn A selector or boolean method for testing elements.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * If a function is used, it receives the current node being tested as the only argument.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @return {Node} Node instance or null if not found
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync previous: function(fn, all) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Node.get(Y.DOM.elementByAxis(g_nodes[this[UID]], 'previousSibling', _wrapFn(fn), all));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /**
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync * Returns the next matching sibling.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Returns the nearest element node sibling if no method provided.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method next
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {String | Function} fn A selector or boolean method for testing elements.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * If a function is used, it receives the current node being tested as the only argument.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @return {Node} Node instance or null if not found
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync next: function(node, fn, all) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Node.get(Y.DOM.elementByAxis(g_nodes[this[UID]], 'nextSibling', _wrapFn(fn), all));
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync /**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Retrieves a Node instance of nodes based on the given CSS selector.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method query
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {string} selector The CSS selector to test against.
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync * @return {Node} A Node instance for the matching HTMLElement.
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync query: function(selector) {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync return Y.get(Y.Selector.query(selector, g_nodes[this[UID]], true));
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Retrieves a nodeList based on the given CSS selector.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method queryAll
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {string} selector The CSS selector to test against.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync queryAll: function(selector) {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync return Y.all(Y.Selector.query(selector, g_nodes[this[UID]]));
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync },
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync // TODO: allow fn test
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync /**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Test if the supplied node matches the supplied selector.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method test
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {string} selector The CSS selector to test against.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @return {boolean} Whether or not the node matches the selector.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync test: function(selector) {
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync return Y.Selector.test(g_nodes[this[UID]], selector);
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync },
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync /**
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync * Removes the node from its parent.
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync * Shortcut for myNode.get('parentNode').removeChild(myNode);
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync * @method remove
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync * @chainable
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync *
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync */
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync remove: function() {
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync var node = g_nodes[this[UID]];
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync node.parentNode.removeChild(node);
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync return this;
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync },
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync
61d7d9128a38eb86895d38f1ad95bdf44fc0b240vboxsync /**
6bbb64124ce2aa00c7f97c8c32b9607e6226b043vboxsync * Invokes a method on the Node instance
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method invoke
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {String} method The name of the method to invoke
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {Any} a, b, c, etc. Arguments to invoke the method with.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @return Whatever the underly method returns.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * DOM Nodes and Collections return values
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync * are converted to Node/NodeList instances.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
2c872d5e527386b5202fb36f281a391aecd82c5fvboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync invoke: function(method, a, b, c, d, e) {
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync var node = g_nodes[this[UID]],
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ret;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (a && a instanceof Y.Node) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync a = Node.getDOMNode(a);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync if (b && b instanceof Y.Node) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync b = Node.getDOMNode(b);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync ret = node[method](a, b, c, d, e);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return Y.Node.scrubVal(ret, this);
0912cf29d2641459d225c40114c567a63273746cvboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync destructor: function() {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync // TODO: What about shared instances?
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync //var uid = this[UID];
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync //delete g_nodes[uid];
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync //delete g_restrict[uid];
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync //delete Node._instances[uid];
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync },
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync
329081e295d2a28a39899b3f919f3c65eef227f0vboxsync /**
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync * Applies the given function to each Node in the NodeList.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method each
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @deprecated Use NodeList
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {Function} fn The function to apply
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync * @param {Object} context optional An optional context to apply the function with
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Default context is the NodeList instance
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @chainable
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync */
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync each: function(fn, context) {
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync context = context || this;
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync Y.log('each is deprecated on Node', 'warn', 'Node');
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync return fn.call(context, this);
3f31fb0be50f57813524420dd94e7c60001313f2vboxsync },
3f31fb0be50f57813524420dd94e7c60001313f2vboxsync
3f31fb0be50f57813524420dd94e7c60001313f2vboxsync /**
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync * Retrieves the Node instance at the given index.
131561c23ec73ceb3818b6df9ff32729642907dbvboxsync * @method item
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @deprecated Use NodeList
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync *
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {Number} index The index of the target Node.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @return {Node} The Node instance at the given index.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
0912cf29d2641459d225c40114c567a63273746cvboxsync item: function(index) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Y.log('item is deprecated on Node', 'warn', 'Node');
0912cf29d2641459d225c40114c567a63273746cvboxsync return this;
0912cf29d2641459d225c40114c567a63273746cvboxsync },
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Returns the current number of items in the Node.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @method size
0912cf29d2641459d225c40114c567a63273746cvboxsync * @deprecated Use NodeList
0912cf29d2641459d225c40114c567a63273746cvboxsync * @return {Int} The number of items in the Node.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
0912cf29d2641459d225c40114c567a63273746cvboxsync size: function() {
0912cf29d2641459d225c40114c567a63273746cvboxsync Y.log('size is deprecated on Node', 'warn', 'Node');
0912cf29d2641459d225c40114c567a63273746cvboxsync return g_nodes[this[UID]] ? 1 : 0;
0912cf29d2641459d225c40114c567a63273746cvboxsync },
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /**
0912cf29d2641459d225c40114c567a63273746cvboxsync * Inserts the content before the reference node.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @method insert
0912cf29d2641459d225c40114c567a63273746cvboxsync * @param {String | Y.Node | HTMLElement} content The content to insert
0912cf29d2641459d225c40114c567a63273746cvboxsync * @param {Int | Y.Node | HTMLElement | String} where The position to insert at.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @chainable
0912cf29d2641459d225c40114c567a63273746cvboxsync */
0912cf29d2641459d225c40114c567a63273746cvboxsync insert: function(content, where) {
0912cf29d2641459d225c40114c567a63273746cvboxsync if (content) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync if (typeof where === 'number') { // allow index
0912cf29d2641459d225c40114c567a63273746cvboxsync where = g_nodes[this[UID]].childNodes[where];
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync if (typeof content !== 'string') { // pass the DOM node
0912cf29d2641459d225c40114c567a63273746cvboxsync content = Y.Node.getDOMNode(content);
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync if (!where || // only allow inserting into this Node's subtree
0912cf29d2641459d225c40114c567a63273746cvboxsync (!g_restrict[this[UID]] ||
0912cf29d2641459d225c40114c567a63273746cvboxsync (typeof where !== 'string' && this.contains(where)))) {
0912cf29d2641459d225c40114c567a63273746cvboxsync Y.DOM.addHTML(g_nodes[this[UID]], content, where);
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync }
0912cf29d2641459d225c40114c567a63273746cvboxsync return this;
e139144ef4fc5f2bbe26be64faf2737cd8ccf413vboxsync },
0912cf29d2641459d225c40114c567a63273746cvboxsync
0912cf29d2641459d225c40114c567a63273746cvboxsync /**
0912cf29d2641459d225c40114c567a63273746cvboxsync * Inserts the content as the firstChild of the node.
0912cf29d2641459d225c40114c567a63273746cvboxsync * @method prepend
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync * @param {String | Y.Node | HTMLElement} content The content to insert
0912cf29d2641459d225c40114c567a63273746cvboxsync * @chainable
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync prepend: function(content) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return this.insert(content, 0);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync /**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Inserts the content as the lastChild of the node.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method append
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @param {String | Y.Node | HTMLElement} content The content to insert
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @chainable
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync append: function(content) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return this.insert(content, null);
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync /**
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync * Replaces the node's current content with the content.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @method setContent
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync * @param {String | Y.Node | HTMLElement} content The content to insert
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @chainable
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync setContent: function(content) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync Y.DOM.addHTML(g_nodes[this[UID]], content, 'replace');
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync return this;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync },
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync // TODO: need this?
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync hasMethod: function(method) {
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync var node = g_nodes[this[UID]];
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync return (node && (typeof node === 'function'));
0912cf29d2641459d225c40114c567a63273746cvboxsync }
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync}, true);
e5967534664502b10b4b92306ad9d12a1a95a55evboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncY.Node = Node;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsyncY.get = Y.Node.get;
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * The NodeList module provides support for managing collections of Nodes.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @module node
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * @submodule nodelist
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync/**
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * The NodeList class provides a wrapper for manipulating DOM NodeLists.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * NodeList properties can be accessed via the set/get methods.
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync * Use Y.all() to retrieve NodeList instances.
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync *
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync * @class NodeList
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync * @constructor
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync */
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsyncY.Array._diff = function(a, b) {
7e37c6180f8e3d8ce94f29fcaaaa046d2466e6a3vboxsync var removed = [],
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync present = false,
dee9e52b1688c0617890cbbd8a8488f9f315d1b7vboxsync i, j, lenA, lenB;
outer:
for (i = 0, lenA = a.length; i < lenA; i++) {
present = false;
for (j = 0, lenB = b.length; j < lenB; j++) {
if (a[i] === b[j]) {
present = true;
continue outer;
}
}
if (!present) {
removed[removed.length] = a[i];
}
}
return removed;
};
Y.Array.diff = function(a, b) {
return {
added: Y.Array._diff(b, a),
removed: Y.Array._diff(a, b)
};
};
var NodeList = function(config) {
var doc = config.doc || Y.config.doc,
nodes = config.nodes || [];
if (typeof nodes === 'string') {
this._query = nodes;
nodes = Y.Selector.query(nodes, doc);
}
Y.stamp(this);
NodeList._instances[this[UID]] = this;
g_nodelists[this[UID]] = nodes;
if (config.restricted) {
g_restrict = this[UID];
}
};
// end "globals"
NodeList.NAME = 'NodeList';
/**
* Retrieves the DOM nodes bound to a NodeList instance
* @method NodeList.getDOMNodes
* @static
*
* @param {Y.NodeList} node The NodeList instance
* @return {Array} The array of DOM nodes bound to the NodeList
*/
NodeList.getDOMNodes = function(nodeList) {
return g_nodelists[nodeList[UID]];
};
NodeList._instances = [];
NodeList.each = function(instance, fn, context) {
var nodes = g_nodelists[instance[UID]];
if (nodes && nodes.length) {
Y.Array.each(nodes, fn, context || instance);
} else {
Y.log('no nodes bound to ' + this, 'warn', 'NodeList');
}
};
NodeList.addMethod = function(name, fn, context) {
var tmp = NodeList._getTempNode();
if (name && fn) {
NodeList.prototype[name] = function() {
var ret = [],
args = arguments;
Y.Array.each(g_nodelists[this[UID]], function(node) {
var UID = '_yuid',
instance = Y.Node._instances[node[UID]],
ctx,
result;
if (!instance) {
g_nodes[tmp[UID]] = node;
instance = tmp;
}
ctx = context || instance;
result = fn.apply(ctx, args);
if (result !== undefined && result !== instance) {
ret[ret.length] = result;
}
});
// TODO: remove tmp pointer
return ret.length ? ret : this;
};
} else {
Y.log('unable to add method: ' + name, 'warn', 'Node');
}
};
NodeList.importMethod = function(host, name, altName) {
if (typeof name === 'string') {
altName = altName || name;
NodeList.addMethod(name, host[name]);
} else {
Y.each(name, function(n) {
NodeList.importMethod(host, n);
});
}
};
NodeList._getTempNode = function() {
var tmp = NodeList._tempNode;
if (!tmp) {
tmp = Y.Node.create('<div></div>');
NodeList._tempNode = tmp;
}
return tmp;
};
Y.mix(NodeList.prototype, {
/**
* Retrieves the Node instance at the given index.
* @method item
*
* @param {Number} index The index of the target Node.
* @return {Node} The Node instance at the given index.
*/
item: function(index) {
return Y.get((g_nodelists[this[UID]] || [])[index]);
},
/**
* Applies the given function to each Node in the NodeList.
* @method each
* @param {Function} fn The function to apply. It receives 3 arguments:
* the current node instance, the node's index, and the NodeList instance
* @param {Object} context optional An optional context to apply the function with
* Default context is the current Node instance
* @chainable
*/
each: function(fn, context) {
var instance = this;
Y.Array.each(g_nodelists[this[UID]], function(node, index) {
node = Y.get(node);
return fn.call(context || node, node, index, instance);
});
return instance;
},
batch: function(fn, context) {
var nodelist = this,
tmp = NodeList._getTempNode();
Y.Array.each(g_nodelists[this[UID]], function(node, index) {
var instance = Y.Node._instances[node[UID]];
if (!instance) {
g_nodes[tmp[UID]] = node;
instance = tmp;
}
return fn.call(context || instance, instance, index, nodelist);
});
return nodelist;
},
/**
* Executes the function once for each node until a true value is returned.
* @method some
* @param {Function} fn The function to apply. It receives 3 arguments:
* the current node instance, the node's index, and the NodeList instance
* @param {Object} context optional An optional context to execute the function from.
* Default context is the current Node instance
* @return {Boolean} Whether or not the function returned true for any node.
*/
some: function(fn, context) {
var instance = this;
return Y.Array.some(g_nodelists[this[UID]], function(node, index) {
node = Y.get(node);
context = context || node;
return fn.call(context, node, index, instance);
});
},
/**
* Returns the index of the node in the NodeList instance
* or -1 if the node isn't found.
* @method indexOf
* @param {Y.Node || DOMNode} node the node to search for
* @return {Int} the index of the node value or -1 if not found
*/
indexOf: function(node) {
return Y.Array.indexOf(g_nodelists[this[UID]], Y.Node.getDOMNode(node));
},
/**
* Filters the NodeList instance down to only nodes matching the given selector.
* @method filter
* @param {String} selector The selector to filter against
* @return {NodeList} NodeList containing the updated collection
* @see Selector
*/
filter: function(selector) {
return Y.all(Y.Selector.filter(g_nodelists[this[UID]], selector));
},
modulus: function(n, r) {
r = r || 0;
var nodes = [];
NodeList.each(this, function(node, i) {
if (i % n === r) {
nodes.push(node);
}
});
return Y.all(nodes);
},
/**
* Creates a new NodeList containing all nodes at odd indices
* (zero-based index).
* @method odd
* @return {NodeList} NodeList containing the updated collection
*/
odd: function() {
return this.modulus(2, 1);
},
/**
* Creates a new NodeList containing all nodes at even indices
* (zero-based index), including zero.
* @method even
* @return {NodeList} NodeList containing the updated collection
*/
even: function() {
return this.modulus(2);
},
destructor: function() {
delete NodeList._instances[this[UID]];
},
refresh: function() {
var doc,
diff,
oldList = g_nodelists[this[UID]];
if (this._query) {
if (g_nodelists[this[UID]] &&
g_nodelists[this[UID]][0] &&
g_nodelists[this[UID]][0].ownerDocument) {
doc = g_nodelists[this[UID]][0].ownerDocument;
}
g_nodelists[this[UID]] = Y.Selector.query(this._query, doc || Y.config.doc);
diff = Y.Array.diff(oldList, g_nodelists[this[UID]]);
diff.added = diff.added ? Y.all(diff.added) : null;
diff.removed = diff.removed ? Y.all(diff.removed) : null;
this.fire('refresh', diff);
}
return this;
},
/**
* Applies an event listener to each Node bound to the NodeList.
* @method on
* @param {String} type The event being listened for
* @param {Function} fn The handler to call when the event fires
* @param {Object} context The context to call the handler with.
* Default is the NodeList instance.
* @return {Object} Returns an event handle that can later be use to detach().
* @see Event.on
*/
on: function(type, fn, context) {
context = context || this;
this.batch(function(node) {
node.on.call(node, type, fn, context);
});
},
/**
* Applies an event listener to each Node bound to the NodeList.
* The handler is called only after all on() handlers are called
* and the event is not prevented.
* @method after
* @param {String} type The event being listened for
* @param {Function} fn The handler to call when the event fires
* @param {Object} context The context to call the handler with.
* Default is the NodeList instance.
* @return {Object} Returns an event handle that can later be use to detach().
* @see Event.on
*/
after: function(type, fn, context) {
context = context || this;
this.batch(function(node) {
node.after.call(node, type, fn, context);
});
},
/**
* Returns the current number of items in the NodeList.
* @method size
* @return {Int} The number of items in the NodeList.
*/
size: function() {
return g_nodelists[this[UID]].length;
},
/** Called on each Node instance
* @get
* @see Node
*/
// one-off because we cant import from Node due to undefined return values
get: function(name) {
var ret = [],
tmp = NodeList._getTempNode();
NodeList.each(this, function(node) {
var instance = Y.Node._instances[node[UID]];
if (!instance) {
g_nodes[tmp[UID]] = node;
instance = tmp;
}
ret[ret.length] = instance.get(name);
});
return ret;
},
toString: function() {
var str = '',
errorMsg = this[UID] + ': not bound to any nodes',
nodes = g_nodelists[this[UID]],
node;
if (nodes && nodes[0]) {
node = nodes[0];
str += node[NODE_NAME];
if (node.id) {
str += '#' + node.id;
}
if (node.className) {
str += '.' + node.className.replace(' ', '.');
}
if (nodes.length > 1) {
str += '...[' + nodes.length + ' items]';
}
}
return str || errorMsg;
}
}, true);
NodeList.importMethod(Y.Node.prototype, [
/**
* Called on each Node instance
* @for NodeList
* @method append
* @see Node.append
*/
'append',
/**
* Called on each Node instance
* @method detach
* @see Node.detach
*/
'detach',
/** Called on each Node instance
* @method detachAll
* @see Node.detachAll
*/
'detachAll',
/** Called on each Node instance
* @method insert
* @see NodeInsert
*/
'insert',
/** Called on each Node instance
* @method plug
* @see Node.plug
*/
'plug',
/** Called on each Node instance
* @method prepend
* @see Node.prepend
*/
'prepend',
/** Called on each Node instance
* @method remove
* @see Node.remove
*/
'remove',
/** Called on each Node instance
* @method set
* @see Node.set
*/
'set',
/** Called on each Node instance
* @method setContent
* @see Node.setContent
*/
'setContent',
/** Called on each Node instance
* @method unplug
* @see Node.unplug
*/
'unplug'
]);
Y.NodeList = NodeList;
Y.all = function(nodes, doc, restrict) {
// TODO: propagate restricted to nodes?
var nodeList = new NodeList({
nodes: nodes,
doc: doc,
restricted: restrict
});
// zero-length result returns null
return nodeList;
};
Y.Node.all = Y.all; // TODO: deprecated
Y.Array.each([
/**
* Passes through to DOM method.
* @method replaceChild
* @for Node
* @param {HTMLElement | Node} node Node to be inserted
* @param {HTMLElement | Node} refNode Node to be replaced
* @return {Node} The replaced node
*/
'replaceChild',
/**
* Passes through to DOM method.
* @method appendChild
* @param {HTMLElement | Node} node Node to be appended
* @return {Node} The appended node
*/
'appendChild',
/**
* Passes through to DOM method.
* @method insertBefore
* @param {HTMLElement | Node} newNode Node to be appended
* @param {HTMLElement | Node} refNode Node to be inserted before
* @return {Node} The inserted node
*/
'insertBefore',
/**
* Passes through to DOM method.
* @method removeChild
* @param {HTMLElement | Node} node Node to be removed
* @return {Node} The removed node
*/
'removeChild',
/**
* Passes through to DOM method.
* @method hasChildNodes
* @return {Boolean} Whether or not the node has any childNodes
*/
'hasChildNodes',
/**
* Passes through to DOM method.
* @method cloneNode
* @param {HTMLElement | Node} node Node to be cloned
* @return {Node} The clone
*/
'cloneNode',
/**
* Passes through to DOM method.
* @method hasAttribute
* @param {String} attribute The attribute to test for
* @return {Boolean} Whether or not the attribute is present
*/
'hasAttribute',
/**
* Passes through to DOM method.
* @method removeAttribute
* @param {String} attribute The attribute to be removed
* @chainable
*/
'removeAttribute',
/**
* Passes through to DOM method.
* @method scrollIntoView
* @chainable
*/
'scrollIntoView',
/**
* Passes through to DOM method.
* @method getElementsByTagName
* @param {String} tagName The tagName to collect
* @return {NodeList} A NodeList representing the HTMLCollection
*/
'getElementsByTagName',
/**
* Passes through to DOM method.
* @method focus
* @chainable
*/
'focus',
/**
* Passes through to DOM method.
* @method blur
* @chainable
*/
'blur',
/**
* Passes through to DOM method.
* Only valid on FORM elements
* @method submit
* @chainable
*/
'submit',
/**
* Passes through to DOM method.
* Only valid on FORM elements
* @method reset
* @chainable
*/
'reset',
/**
* Passes through to DOM method.
* @method select
* @chainable
*/
'select'
], function(method) {
Y.Node.prototype[method] = function(arg1, arg2, arg3) {
var ret = this.invoke(method, arg1, arg2, arg3);
return ret;
};
});
Node.importMethod(Y.DOM, [
/**
* Determines whether the ndoe is an ancestor of another HTML element in the DOM hierarchy.
* @method contains
* @param {Node | HTMLElement} needle The possible node or descendent
* @return {Boolean} Whether or not this node is the needle its ancestor
*/
'contains',
/**
* Allows setting attributes on DOM nodes, normalizing in some cases.
* This passes through to the DOM node, allowing for custom attributes.
* @method setAttribute
* @for Node
* @for NodeList
* @chainable
* @param {string} name The attribute name
* @param {string} value The value to set
*/
'setAttribute',
/**
* Allows getting attributes on DOM nodes, normalizing in some cases.
* This passes through to the DOM node, allowing for custom attributes.
* @method getAttribute
* @for Node
* @for NodeList
* @param {string} name The attribute name
* @return {string} The attribute value
*/
'getAttribute'
]);
if (!document.documentElement.hasAttribute) { // IE < 8
Y.Node.prototype.hasAttribute = function(attr) {
return Y.DOM.getAttribute(Y.Node.getDOMNode(this), attr) !== '';
};
}
/**
* Allows setting attributes on DOM nodes, normalizing in some cases.
* This passes through to the DOM node, allowing for custom attributes.
* @method setAttribute
* @see Node
* @for NodeList
* @chainable
* @param {string} name The attribute name
* @param {string} value The value to set
*/
/**
* Allows getting attributes on DOM nodes, normalizing in some cases.
* This passes through to the DOM node, allowing for custom attributes.
* @method getAttribute
* @see Node
* @for NodeList
* @param {string} name The attribute name
* @return {string} The attribute value
*/
Y.NodeList.importMethod(Y.Node.prototype, ['getAttribute', 'setAttribute']);
(function() { // IE clones expandos; regenerate UID
var node = document.createElement('div'),
UID = '_yuid';
Y.stamp(node);
if (node[UID] === node.cloneNode(true)[UID]) {
Y.Node.prototype.cloneNode = function(deep) {
var node = Y.Node.getDOMNode(this).cloneNode(deep);
node[UID] = Y.guid();
return Y.get(node);
};
}
})();
(function(Y) {
var methods = [
/**
* Determines whether each node has the given className.
* @method hasClass
* @for Node
* @param {String} className the class name to search for
* @return {Array} An array of booleans for each node bound to the NodeList.
*/
'hasClass',
/**
* Adds a class name to each node.
* @method addClass
* @param {String} className the class name to add to the node's class attribute
* @chainable
*/
'addClass',
/**
* Removes a class name from each node.
* @method removeClass
* @param {String} className the class name to remove from the node's class attribute
* @chainable
*/
'removeClass',
/**
* Replace a class with another class for each node.
* If no oldClassName is present, the newClassName is simply added.
* @method replaceClass
* @param {String} oldClassName the class name to be replaced
* @param {String} newClassName the class name that will be replacing the old class name
* @chainable
*/
'replaceClass',
/**
* If the className exists on the node it is removed, if it doesn't exist it is added.
* @method toggleClass
* @param {String} className the class name to be toggled
* @chainable
*/
'toggleClass'
];
Y.Node.importMethod(Y.DOM, methods);
/**
* Determines whether each node has the given className.
* @method hasClass
* @see Node.hasClass
* @for NodeList
* @param {String} className the class name to search for
* @return {Array} An array of booleans for each node bound to the NodeList.
*/
/**
* Adds a class name to each node.
* @method addClass
* @see Node.addClass
* @param {String} className the class name to add to the node's class attribute
* @chainable
*/
/**
* Removes a class name from each node.
* @method removeClass
* @see Node.removeClass
* @param {String} className the class name to remove from the node's class attribute
* @chainable
*/
/**
* Replace a class with another class for each node.
* If no oldClassName is present, the newClassName is simply added.
* @method replaceClass
* @see Node.replaceClass
* @param {String} oldClassName the class name to be replaced
* @param {String} newClassName the class name that will be replacing the old class name
* @chainable
*/
/**
* If the className exists on the node it is removed, if it doesn't exist it is added.
* @method toggleClass
* @see Node.toggleClass
* @param {String} className the class name to be toggled
* @chainable
*/
Y.NodeList.importMethod(Y.Node.prototype, methods);
})(Y);
/**
* Functionality to make the node a delegated event container
* @module node
* @submodule node-event-delegate
*/
/**
* Functionality to make the node a delegated event container
* @method delegate
* @param type {String} the event type to delegate
* @param fn {Function} the function to execute
* @param selector {String} a selector that must match the target of the event.
* @return {Event.Handle} the detach handle
* @for Node
*/
Y.Node.prototype.delegate = function(type, fn, selector, context) {
context = context || this;
var args = Array.prototype.slice.call(arguments, 4),
a = ['delegate', fn, Y.Node.getDOMNode(this), type, selector, context];
a = a.concat(args);
return Y.on.apply(Y, a);
};
var onMutation = function(e) {
var node = Y.Node._instances[e.relatedNode._yuid],
type,
evt,
field;
console.log(e, node);
// only process if someone is listening
if (node && node._yuievt && node._yuievt.events[type]) {
type = e.type.substring(3);
evt = {};
for (field in e) {
if (e[field].nodeType) {
evt[field] = Y.get(e[field]);
} else {
evt[field] = e[field];
}
}
evt.type = type;
node.fire(type, evt);
}
};
Y.config.doc.addEventListener('DOMAttrModified', onMutation, 0);
Y.config.doc.addEventListener('DOMNodeInserted', onMutation, 0);
Y.config.doc.addEventListener('DOMNodeRemoved', onMutation, 0);
}, '@VERSION@' ,{requires:['dom-base', 'base', 'selector']});
YUI.add('node-style', function(Y) {
(function(Y) {
/**
* Extended Node interface for managing node styles.
* @module node
* @submodule node-style
*/
var methods = [
/**
* Returns the style's current value.
* @method getStyle
* @for Node
* @param {String} attr The style attribute to retrieve.
* @return {String} The current value of the style property for the element.
*/
'getStyle',
/**
* Returns the computed value for the given style property.
* @method getComputedStyle
* @param {String} attr The style attribute to retrieve.
* @return {String} The computed value of the style property for the element.
*/
'getComputedStyle',
/**
* Sets a style property of the node.
* @method setStyle
* @param {String} attr The style attribute to set.
* @param {String|Number} val The value.
* @chainable
*/
'setStyle',
/**
* Sets multiple style properties on the node.
* @method setStyles
* @param {Object} hash An object literal of property:value pairs.
* @chainable
*/
'setStyles'
];
Y.Node.importMethod(Y.DOM, methods);
/**
* Returns an array of values for each node.
* @method getStyle
* @for NodeList
* @see Node.getStyle
* @param {String} attr The style attribute to retrieve.
* @return {Array} The current values of the style property for the element.
*/
/**
* Returns an array of the computed value for each node.
* @method getComputedStyle
* @see Node.getComputedStyle
* @param {String} attr The style attribute to retrieve.
* @return {Array} The computed values for each node.
*/
'getComputedStyle',
/**
* Sets a style property on each node.
* @method setStyle
* @see Node.setStyle
* @param {String} attr The style attribute to set.
* @param {String|Number} val The value.
* @chainable
*/
'setStyle',
/**
* Sets multiple style properties on each node.
* @method setStyles
* @see Node.setStyles
* @param {Object} hash An object literal of property:value pairs.
* @chainable
*/
'setStyles'
Y.NodeList.importMethod(Y.Node.prototype, methods);
})(Y);
}, '@VERSION@' ,{requires:['dom-style', 'node-base']});
YUI.add('node-screen', function(Y) {
/**
* Extended Node interface for managing regions and screen positioning.
* Adds support for positioning elements and normalizes window size and scroll detection.
* @module node
* @submodule node-screen
*/
// these are all "safe" returns, no wrapping required
Y.each([
/**
* Returns the inner width of the viewport (exludes scrollbar).
* @config winWidth
* @for Node
* @type {Int}
*/
'winWidth',
/**
* Returns the inner height of the viewport (exludes scrollbar).
* @config winHeight
* @type {Int}
*/
'winHeight',
/**
* Document width
* @config winHeight
* @type {Int}
*/
'docWidth',
/**
* Document height
* @config docHeight
* @type {Int}
*/
'docHeight',
/**
* Amount page has been scroll vertically
* @config docScrollX
* @type {Int}
*/
'docScrollX',
/**
* Amount page has been scroll horizontally
* @config docScrollY
* @type {Int}
*/
'docScrollY'
],
function(name) {
Y.Node.ATTRS[name] = {
getter: function() {
var args = Array.prototype.slice.call(arguments);
args.unshift(Y.Node.getDOMNode(this));
return Y.DOM[name].apply(this, args);
}
};
}
);
Y.Node.ATTRS.scrollLeft = {
getter: function() {
var node = Y.Node.getDOMNode(this);
return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node);
},
setter: function(val) {
var node = Y.Node.getDOMNode(this);
if (node) {
if ('scrollLeft' in node) {
node.scrollLeft = val;
} else if (node.document || node.nodeType === 9) {
Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc
}
} else {
Y.log('unable to set scrollLeft for ' + node, 'error', 'Node');
}
}
};
Y.Node.ATTRS.scrollTop = {
getter: function() {
var node = Y.Node.getDOMNode(this);
return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node);
},
setter: function(val) {
var node = Y.Node.getDOMNode(this);
if (node) {
if ('scrollTop' in node) {
node.scrollTop = val;
} else if (node.document || node.nodeType === 9) {
Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc
}
} else {
Y.log('unable to set scrollTop for ' + node, 'error', 'Node');
}
}
};
Y.Node.importMethod(Y.DOM, [
/**
* Gets the current position of the node in page coordinates.
* @method getXY
* @for Node
* @return {Array} The XY position of the node
*/
'getXY',
/**
* Set the position of the node in page coordinates, regardless of how the node is positioned.
* @method setXY
* @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
* @chainable
*/
'setXY',
/**
* Gets the current position of the node in page coordinates.
* @method getX
* @return {Int} The X position of the node
*/
'getX',
/**
* Set the position of the node in page coordinates, regardless of how the node is positioned.
* @method setX
* @param {Int} x X value for new position (coordinates are page-based)
* @chainable
*/
'setX',
/**
* Gets the current position of the node in page coordinates.
* @method getY
* @return {Int} The Y position of the node
*/
'getY',
/**
* Set the position of the node in page coordinates, regardless of how the node is positioned.
* @method setY
* @param {Int} y Y value for new position (coordinates are page-based)
* @chainable
*/
'setY'
]);
/**
* Returns a region object for the node
* @config region
* @for Node
* @type Node
*/
Y.Node.ATTRS.region = {
getter: function() {
var node = Y.Node.getDOMNode(this);
if (node && !node.tagName) {
if (node.nodeType === 9) { // document
node = node.documentElement;
} else if (node.alert) { // window
node = node.document.documentElement;
}
}
return Y.DOM.region(node);
}
};
/**
* Returns a region object for the node's viewport
* @config viewportRegion
* @type Node
*/
Y.Node.ATTRS.viewportRegion = {
getter: function() {
return Y.DOM.viewportRegion(Y.Node.getDOMNode(this));
}
};
Y.Node.importMethod(Y.DOM, 'inViewportRegion');
// these need special treatment to extract 2nd node arg
/**
* Compares the intersection of the node with another node or region
* @method intersect
* @for Node
* @param {Node|Object} node2 The node or region to compare with.
* @param {Object} altRegion An alternate region to use (rather than this node's).
* @return {Object} An object representing the intersection of the regions.
*/
Y.Node.prototype.intersect = function(node2, altRegion) {
var node1 = Y.Node.getDOMNode(this);
if (node2 instanceof Y.Node) { // might be a region object
node2 = Y.Node.getDOMNode(node2);
}
return Y.DOM.intersect(node1, node2, altRegion);
};
/**
* Determines whether or not the node is within the giving region.
* @method inRegion
* @param {Node|Object} node2 The node or region to compare with.
* @param {Boolean} all Whether or not all of the node must be in the region.
* @param {Object} altRegion An alternate region to use (rather than this node's).
* @return {Object} An object representing the intersection of the regions.
*/
Y.Node.prototype.inRegion = function(node2, all, altRegion) {
var node1 = Y.Node.getDOMNode(this);
if (node2 instanceof Y.Node) { // might be a region object
node2 = Y.Node.getDOMNode(node2);
}
return Y.DOM.inRegion(node1, node2, all, altRegion);
};
}, '@VERSION@' ,{requires:['dom-screen']});
YUI.add('node', function(Y){}, '@VERSION@' ,{use:['node-base', 'node-style', 'node-screen'], skinnable:false, requires:['dom']});