Current Path : C:/xampp/htdocs/moodle/lib/yuilib/3.17.2/node-base/ |
Current File : C:/xampp/htdocs/moodle/lib/yuilib/3.17.2/node-base/node-base.js |
/* YUI 3.17.2 (build 9c3c78e) Copyright 2014 Yahoo! Inc. All rights reserved. Licensed under the BSD License. http://yuilibrary.com/license/ */ YUI.add('node-base', function (Y, NAME) { /** * @module node * @submodule node-base */ var methods = [ /** * Determines whether the node has the given className. * @method hasClass * @for Node * @param {String} className the class name to search for * @return {Boolean} Whether or not the node has the specified class */ 'hasClass', /** * Adds a class name to the node. * @method addClass * @param {String} className the class name to add to the node's class attribute * @chainable */ 'addClass', /** * Removes a class name from the 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 on the 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 * @param {Boolean} force Option to force adding or removing the class. * @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 each 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 each 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 */ /** * For each node, 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); /** * @module node * @submodule node-base */ var Y_Node = Y.Node, Y_DOM = Y.DOM; /** * Returns a new dom node using the provided markup string. * @method create * @static * @param {String} html The markup used to create the element. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content. * @param {HTMLDocument} doc An optional document context * @return {Node} A Node instance bound to a DOM node or fragment * @for Node */ Y_Node.create = function(html, doc) { if (doc && doc._node) { doc = doc._node; } return Y.one(Y_DOM.create(html, doc)); }; Y.mix(Y_Node.prototype, { /** * Creates a new Node using the provided markup string. * @method create * @param {String} html The markup used to create the element. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content. * @param {HTMLDocument} doc An optional document context * @return {Node} A Node instance bound to a DOM node or fragment */ create: Y_Node.create, /** * Inserts the content before the reference node. * @method insert * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content. * @param {Int | Node | HTMLElement | String} where The position to insert at. * Possible "where" arguments * <dl> * <dt>Y.Node</dt> * <dd>The Node to insert before</dd> * <dt>HTMLElement</dt> * <dd>The element to insert before</dd> * <dt>Int</dt> * <dd>The index of the child element to insert before</dd> * <dt>"replace"</dt> * <dd>Replaces the existing HTML</dd> * <dt>"before"</dt> * <dd>Inserts before the existing HTML</dd> * <dt>"before"</dt> * <dd>Inserts content before the node</dd> * <dt>"after"</dt> * <dd>Inserts content after the node</dd> * </dl> * @chainable */ insert: function(content, where) { this._insert(content, where); return this; }, _insert: function(content, where) { var node = this._node, ret = null; if (typeof where == 'number') { // allow index where = this._node.childNodes[where]; } else if (where && where._node) { // Node where = where._node; } if (content && typeof content != 'string') { // allow Node or NodeList/Array instances content = content._node || content._nodes || content; } ret = Y_DOM.addHTML(node, content, where); return ret; }, /** * Inserts the content as the firstChild of the node. * @method prepend * @param {String | Node | HTMLElement} content The content to insert. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content. * @chainable */ prepend: function(content) { return this.insert(content, 0); }, /** * Inserts the content as the lastChild of the node. * @method append * @param {String | Node | HTMLElement} content The content to insert. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content. * @chainable */ append: function(content) { return this.insert(content, null); }, /** * @method appendChild * @param {String | HTMLElement | Node} node Node to be appended. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content. * @return {Node} The appended node */ appendChild: function(node) { return Y_Node.scrubVal(this._insert(node)); }, /** * @method insertBefore * @param {String | HTMLElement | Node} newNode Node to be appended * @param {HTMLElement | Node} refNode Node to be inserted before. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content. * @return {Node} The inserted node */ insertBefore: function(newNode, refNode) { return Y.Node.scrubVal(this._insert(newNode, refNode)); }, /** * Appends the node to the given node. * @example * // appendTo returns the node that has been created beforehand * Y.Node.create('<p></p>').appendTo('body').set('text', 'hello world!'); * @method appendTo * @param {Node | HTMLElement | String} node The node to append to. * If `node` is a string it will be considered as a css selector and only the first matching node will be used. * @chainable */ appendTo: function(node) { Y.one(node).append(this); return this; }, // This method is deprecated, and is intentionally left undocumented. // Use `setHTML` instead. setContent: function(content) { this._insert(content, 'replace'); return this; }, // This method is deprecated, and is intentionally left undocumented. // Use `getHTML` instead. getContent: function() { var node = this; if (node._node.nodeType === 11) { // 11 === Node.DOCUMENT_FRAGMENT_NODE // "this", when it is a document fragment, must be cloned because // the nodes contained in the fragment actually disappear once // the fragment is appended anywhere node = node.create("<div/>").append(node.cloneNode(true)); } return node.get("innerHTML"); } }); /** * Replaces the node's current html content with the content provided. * Note that this passes to innerHTML and is not escaped. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content or `set('text')` to add as text. * @method setHTML * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert * @chainable */ Y.Node.prototype.setHTML = Y.Node.prototype.setContent; /** * Returns the node's current html content (e.g. innerHTML) * @method getHTML * @return {String} The html content */ Y.Node.prototype.getHTML = Y.Node.prototype.getContent; Y.NodeList.importMethod(Y.Node.prototype, [ /** * Called on each Node instance * @for NodeList * @method append * @see Node.append */ 'append', /** * Called on each Node instance * @for NodeList * @method insert * @see Node.insert */ 'insert', /** * Called on each Node instance * @for NodeList * @method appendChild * @see Node.appendChild */ 'appendChild', /** * Called on each Node instance * @for NodeList * @method insertBefore * @see Node.insertBefore */ 'insertBefore', /** * Called on each Node instance * @for NodeList * @method prepend * @see Node.prepend */ 'prepend', 'setContent', 'getContent', /** * Called on each Node instance * Note that this passes to innerHTML and is not escaped. * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a> * to escape html content or `set('text')` to add as text. * @for NodeList * @method setHTML * @see Node.setHTML */ 'setHTML', /** * Called on each Node instance * @for NodeList * @method getHTML * @see Node.getHTML */ 'getHTML' ]); /** * @module node * @submodule node-base */ var Y_Node = Y.Node, Y_DOM = Y.DOM; /** * Static collection of configuration attributes for special handling * @property ATTRS * @static * @type object */ Y_Node.ATTRS = { /** * Allows for getting and setting the text of an element. * Formatting is preserved and special characters are treated literally. * @config text * @type String */ text: { getter: function() { return Y_DOM.getText(this._node); }, setter: function(content) { Y_DOM.setText(this._node, content); return content; } }, /** * Allows for getting and setting the text of an element. * Formatting is preserved and special characters are treated literally. * @config for * @type String */ 'for': { getter: function() { return Y_DOM.getAttribute(this._node, 'for'); }, setter: function(val) { Y_DOM.setAttribute(this._node, 'for', val); return val; } }, 'options': { getter: function() { return this._node.getElementsByTagName('option'); } }, /** * Returns a NodeList instance of all HTMLElement children. * @readOnly * @config children * @type NodeList */ 'children': { getter: function() { var node = this._node, children = node.children, childNodes, i, len; if (!children) { childNodes = node.childNodes; children = []; for (i = 0, len = childNodes.length; i < len; ++i) { if (childNodes[i].tagName) { children[children.length] = childNodes[i]; } } } return Y.all(children); } }, value: { getter: function() { return Y_DOM.getValue(this._node); }, setter: function(val) { Y_DOM.setValue(this._node, val); return val; } } }; Y.Node.importMethod(Y.DOM, [ /** * 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' ]); /** * @module node * @submodule node-base */ var Y_Node = Y.Node; var Y_NodeList = Y.NodeList; /** * List of events that route to DOM events * @static * @property DOM_EVENTS * @for Node */ Y_Node.DOM_EVENTS = { abort: 1, beforeunload: 1, blur: 1, change: 1, click: 1, close: 1, command: 1, contextmenu: 1, copy: 1, cut: 1, dblclick: 1, DOMMouseScroll: 1, drag: 1, dragstart: 1, dragenter: 1, dragover: 1, dragleave: 1, dragend: 1, drop: 1, error: 1, focus: 1, key: 1, keydown: 1, keypress: 1, keyup: 1, load: 1, message: 1, mousedown: 1, mouseenter: 1, mouseleave: 1, mousemove: 1, mousemultiwheel: 1, mouseout: 1, mouseover: 1, mouseup: 1, mousewheel: 1, orientationchange: 1, paste: 1, reset: 1, resize: 1, select: 1, selectstart: 1, submit: 1, scroll: 1, textInput: 1, unload: 1, invalid: 1 }; // Add custom event adaptors to this list. This will make it so // that delegate, key, available, contentready, etc all will // be available through Node.on Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins); Y.augment(Y_Node, Y.EventTarget); Y.mix(Y_Node.prototype, { /** * Removes event listeners from the node and (optionally) its subtree * @method purge * @param {Boolean} recurse (optional) Whether or not to remove listeners from the * node's subtree * @param {String} type (optional) Only remove listeners of the specified type * @chainable * */ purge: function(recurse, type) { Y.Event.purgeElement(this._node, recurse, type); return this; } }); Y.mix(Y.NodeList.prototype, { _prepEvtArgs: function(type, fn, context) { // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc) var args = Y.Array(arguments, 0, true); if (args.length < 2) { // type only (event hash) just add nodes args[2] = this._nodes; } else { args.splice(2, 0, this._nodes); } args[3] = context || this; // default to NodeList instance as context return args; }, /** Subscribe a callback function for each `Node` in the collection to execute in response to a DOM event. NOTE: Generally, the `on()` method should be avoided on `NodeLists`, in favor of using event delegation from a parent Node. See the Event user guide for details. Most DOM events are associated with a preventable default behavior, such as link clicks navigating to a new page. Callbacks are passed a `DOMEventFacade` object as their first argument (usually called `e`) that can be used to prevent this default behavior with `e.preventDefault()`. See the `DOMEventFacade` API for all available properties and methods on the object. By default, the `this` object will be the `NodeList` that the subscription came from, <em>not the `Node` that received the event</em>. Use `e.currentTarget` to refer to the `Node`. Returning `false` from a callback is supported as an alternative to calling `e.preventDefault(); e.stopPropagation();`. However, it is recommended to use the event methods. @example Y.all(".sku").on("keydown", function (e) { if (e.keyCode === 13) { e.preventDefault(); // Use e.currentTarget to refer to the individual Node var item = Y.MyApp.searchInventory( e.currentTarget.get('value') ); // etc ... } }); @method on @param {String} type The name of the event @param {Function} fn The callback to execute in response to the event @param {Object} [context] Override `this` object in callback @param {Any} [arg*] 0..n additional arguments to supply to the subscriber @return {EventHandle} A subscription handle capable of detaching that subscription @for NodeList **/ on: function(type, fn, context) { return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments)); }, /** * Applies an one-time event listener to each Node bound to the NodeList. * @method once * @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 {EventHandle} A subscription handle capable of detaching that * subscription * @for NodeList */ once: function(type, fn, context) { return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments)); }, /** * 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 {EventHandle} A subscription handle capable of detaching that * subscription * @for NodeList */ after: function(type, fn, context) { return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments)); }, /** * Applies an one-time event listener to each Node bound to the NodeList * that will be called only after all on() handlers are called and the * event is not prevented. * * @method onceAfter * @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 {EventHandle} A subscription handle capable of detaching that * subscription * @for NodeList */ onceAfter: function(type, fn, context) { return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments)); } }); Y_NodeList.importMethod(Y.Node.prototype, [ /** * Called on each Node instance * @method detach * @see Node.detach * @for NodeList */ 'detach', /** Called on each Node instance * @method detachAll * @see Node.detachAll * @for NodeList */ 'detachAll' ]); /** Subscribe a callback function to execute in response to a DOM event or custom event. Most DOM events are associated with a preventable default behavior such as link clicks navigating to a new page. Callbacks are passed a `DOMEventFacade` object as their first argument (usually called `e`) that can be used to prevent this default behavior with `e.preventDefault()`. See the `DOMEventFacade` API for all available properties and methods on the object. If the event name passed as the first parameter is not a whitelisted DOM event, it will be treated as a custom event subscriptions, allowing `node.fire('customEventName')` later in the code. Refer to the Event user guide for the full DOM event whitelist. By default, the `this` object in the callback will refer to the subscribed `Node`. Returning `false` from a callback is supported as an alternative to calling `e.preventDefault(); e.stopPropagation();`. However, it is recommended to use the event methods. @example Y.one("#my-form").on("submit", function (e) { e.preventDefault(); // proceed with ajax form submission instead... }); @method on @param {String} type The name of the event @param {Function} fn The callback to execute in response to the event @param {Object} [context] Override `this` object in callback @param {Any} [arg*] 0..n additional arguments to supply to the subscriber @return {EventHandle} A subscription handle capable of detaching that subscription @for Node **/ Y.mix(Y.Node.ATTRS, { offsetHeight: { setter: function(h) { Y.DOM.setHeight(this._node, h); return h; }, getter: function() { return this._node.offsetHeight; } }, offsetWidth: { setter: function(w) { Y.DOM.setWidth(this._node, w); return w; }, getter: function() { return this._node.offsetWidth; } } }); Y.mix(Y.Node.prototype, { sizeTo: function(w, h) { var node; if (arguments.length < 2) { node = Y.one(w); w = node.get('offsetWidth'); h = node.get('offsetHeight'); } this.setAttrs({ offsetWidth: w, offsetHeight: h }); } }); if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8 Y.Node.prototype.hasAttribute = function(attr) { if (attr === 'value') { if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML return true; } } return !!(this._node.attributes[attr] && this._node.attributes[attr].specified); }; } // IE throws an error when calling focus() on an element that's invisible, not // displayed, or disabled. Y.Node.prototype.focus = function () { try { this._node.focus(); } catch (e) { } return this; }; // IE throws error when setting input.type = 'hidden', // input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden' Y.Node.ATTRS.type = { setter: function(val) { if (val === 'hidden') { try { this._node.type = 'hidden'; } catch(e) { this._node.style.display = 'none'; this._inputType = 'hidden'; } } else { try { // IE errors when changing the type from "hidden' this._node.type = val; } catch (e) { } } return val; }, getter: function() { return this._inputType || this._node.type; }, _bypassProxy: true // don't update DOM when using with Attribute }; if (Y.config.doc.createElement('form').elements.nodeType) { // IE: elements collection is also FORM node which trips up scrubVal. Y.Node.ATTRS.elements = { getter: function() { return this.all('input, textarea, button, select'); } }; } /** * Provides methods for managing custom Node data. * * @module node * @main node * @submodule node-data */ Y.mix(Y.Node.prototype, { _initData: function() { if (! ('_data' in this)) { this._data = {}; } }, /** * @method getData * @for Node * @description Retrieves arbitrary data stored on a Node instance. * If no data is associated with the Node, it will attempt to retrieve * a value from the corresponding HTML data attribute. (e.g. node.getData('foo') * will check node.getAttribute('data-foo')). * @param {string} name Optional name of the data field to retrieve. * If no name is given, all data is returned. * @return {any | Object} Whatever is stored at the given field, * or an object hash of all fields. */ getData: function(name) { this._initData(); var data = this._data, ret = data; if (arguments.length) { // single field if (name in data) { ret = data[name]; } else { // initialize from HTML attribute ret = this._getDataAttribute(name); } } else if (typeof data == 'object' && data !== null) { // all fields ret = {}; Y.Object.each(data, function(v, n) { ret[n] = v; }); ret = this._getDataAttributes(ret); } return ret; }, _getDataAttributes: function(ret) { ret = ret || {}; var i = 0, attrs = this._node.attributes, len = attrs.length, prefix = this.DATA_PREFIX, prefixLength = prefix.length, name; while (i < len) { name = attrs[i].name; if (name.indexOf(prefix) === 0) { name = name.substr(prefixLength); if (!(name in ret)) { // only merge if not already stored ret[name] = this._getDataAttribute(name); } } i += 1; } return ret; }, _getDataAttribute: function(name) { name = this.DATA_PREFIX + name; var node = this._node, attrs = node.attributes, data = attrs && attrs[name] && attrs[name].value; return data; }, /** * @method setData * @for Node * @description Stores arbitrary data on a Node instance. * This is not stored with the DOM node. * @param {string} name The name of the field to set. If no val * is given, name is treated as the data and overrides any existing data. * @param {any} val The value to be assigned to the field. * @chainable */ setData: function(name, val) { this._initData(); if (arguments.length > 1) { this._data[name] = val; } else { this._data = name; } return this; }, /** * @method clearData * @for Node * @description Clears internally stored data. * @param {string} name The name of the field to clear. If no name * is given, all data is cleared. * @chainable */ clearData: function(name) { if ('_data' in this) { if (typeof name != 'undefined') { delete this._data[name]; } else { delete this._data; } } return this; } }); Y.mix(Y.NodeList.prototype, { /** * @method getData * @for NodeList * @description Retrieves arbitrary data stored on each Node instance * bound to the NodeList. * @see Node * @param {string} name Optional name of the data field to retrieve. * If no name is given, all data is returned. * @return {Array} An array containing all of the data for each Node instance. * or an object hash of all fields. */ getData: function(name) { var args = (arguments.length) ? [name] : []; return this._invoke('getData', args, true); }, /** * @method setData * @for NodeList * @description Stores arbitrary data on each Node instance bound to the * NodeList. This is not stored with the DOM node. * @param {string} name The name of the field to set. If no name * is given, name is treated as the data and overrides any existing data. * @param {any} val The value to be assigned to the field. * @chainable */ setData: function(name, val) { var args = (arguments.length > 1) ? [name, val] : [name]; return this._invoke('setData', args); }, /** * @method clearData * @for NodeList * @description Clears data on all Node instances bound to the NodeList. * @param {string} name The name of the field to clear. If no name * is given, all data is cleared. * @chainable */ clearData: function(name) { var args = (arguments.length) ? [name] : []; return this._invoke('clearData', [name]); } }); }, '3.17.2', {"requires": ["event-base", "node-core", "dom-base", "dom-style"]});