/** * @class Ext.dom.AbstractElement * @private */ (function() { var document = window.document; if (!Ext.cache){ Ext.cache = {}; } Ext.define('Ext.dom.AbstractElement', { inheritableStatics: { /** * Retrieves Ext.dom.Element objects. {@link Ext#get} is alias for {@link Ext.dom.Element#get}. * * **This method does not retrieve {@link Ext.Component Component}s.** This method retrieves Ext.dom.Element * objects which encapsulate DOM elements. To retrieve a Component by its ID, use {@link Ext.ComponentManager#get}. * * Uses simple caching to consistently return the same object. Automatically fixes if an object was recreated with * the same id via AJAX or DOM. * * @param {String/HTMLElement/Ext.Element} el The id of the node, a DOM Node or an existing Element. * @return {Ext.dom.Element} The Element object (or null if no matching element was found) * @static * @inheritable */ get: function(el) { var me = this, El = Ext.dom.Element, extEl, dom, id; if (!el) { return null; } if (typeof el == "string") { // element id if (!(dom = document.getElementById(el))) { return null; } if (Ext.cache[el] && Ext.cache[el].el) { extEl = Ext.cache[el].el; extEl.dom = dom; } else { extEl = me.addToCache(new El(dom)); } return extEl; } else if (el.tagName) { // dom element if (!(id = el.id)) { id = Ext.id(el); } if (Ext.cache[id] && Ext.cache[id].el) { extEl = Ext.cache[id].el; extEl.dom = el; } else { extEl = me.addToCache(new El(el)); } return extEl; } else if (el instanceof me) { if (el != me.docEl) { // refresh dom element in case no longer valid, // catch case where it hasn't been appended el.dom = document.getElementById(el.id) || el.dom; } return el; } else if (el.isComposite) { return el; } else if (Ext.isArray(el)) { return me.select(el); } else if (el == document) { // create a bogus element object representing the document object if (!me.docEl) { me.docEl = Ext.Object.chain(El.prototype); me.docEl.dom = document; document.documentElement.id = me.docEl.id = Ext.id(document); } return me.docEl; } return null; }, addToCache: function(el, id) { if (el) { id = id || el.id; Ext.cache[id] = { el: el, data: {}, events: {} }; } return el; }, // private method for getting and setting element data data: function(el, key, value) { el = this.get(el); if (!el) { return null; } var c = Ext.cache[el.id].data; if (!c) { c = Ext.cache[el.id].data = {}; } if (arguments.length == 2) { return c[key]; } else { return (c[key] = value); } }, addMethods: function() { this.override.apply(this, arguments); }, /** * @property * Visibility mode constant for use with {@link #setVisibilityMode}. Use visibility to hide element * @static */ VISIBILITY: 1, /** * @property * Visibility mode constant for use with {@link #setVisibilityMode}. Use display to hide element * @static */ DISPLAY: 2, /** * @property * Visibility mode constant for use with {@link #setVisibilityMode}. Use offsets to hide element * @static */ OFFSETS: 3 }, constructor: function(element, forceNew) { var dom = typeof element == 'string' ? document.getElementById(element) : element, id; if (!dom) { return null; } id = dom.id; if (!forceNew && id && Ext.cache[id]) { // element object already exists return Ext.cache[id].el; } /** * @property {HTMLElement} dom * The DOM element */ this.dom = dom; /** * @property {String} id * The DOM element ID */ this.id = id || Ext.id(dom); }, attach: function (dom) { this.dom = dom; this.id = dom.id; return this; }, /** * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function) * @param {Object} o The object with the attributes * @param {Boolean} [useSet=true] false to override the default setAttribute to use expandos. * @return {Ext.dom.Element} this */ set: function(o, useSet) { var el = this.dom, attr, value; for (attr in o) { if (o.hasOwnProperty(attr)) { value = o[attr]; if (attr == 'style') { this.applyStyles(value); } else if (attr == 'cls') { el.className = value; } else if (useSet !== false) { if (value === undefined) { el.removeAttribute(attr); } else { el.setAttribute(attr, value); } } else { el[attr] = value; } } } return this; }, /** * @property {String} defaultUnit * The default unit to append to CSS values where a unit isn't provided. */ defaultUnit: "px", /** * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child) * @param {String} selector The simple selector to test * @return {Boolean} True if this element matches the selector, else false */ is: function(simpleSelector) { return Ext.DomQuery.is(this.dom, simpleSelector); }, /** * Returns the value of the "value" attribute * @param {Boolean} asNumber true to parse the value as a number * @return {String/Number} */ getValue: function(asNumber) { var val = this.dom.value; return asNumber ? parseInt(val, 10) : val; }, /** * Removes this element's dom reference. Note that event and cache removal is handled at {@link Ext#removeNode * Ext.removeNode} */ remove: function() { var me = this, dom = me.dom; if (dom) { delete me.dom; Ext.removeNode(dom); } }, /** * Returns true if this element is an ancestor of the passed element * @param {HTMLElement/String} el The element to check * @return {Boolean} True if this element is an ancestor of el, else false */ contains: function(el) { if (!el) { return false; } var me = this, dom = el.dom || el; // we need el-contains-itself logic here because isAncestor does not do that: return (dom === me.dom) || Ext.dom.AbstractElement.isAncestor(me.dom, dom); }, /** * Returns the value of an attribute from the element's underlying DOM node. * @param {String} name The attribute name * @param {String} [namespace] The namespace in which to look for the attribute * @return {String} The attribute value */ getAttribute: function(name, ns) { var dom = this.dom; return dom.getAttributeNS(ns, name) || dom.getAttribute(ns + ":" + name) || dom.getAttribute(name) || dom[name]; }, /** * Update the innerHTML of this element * @param {String} html The new HTML * @return {Ext.dom.Element} this */ update: function(html) { if (this.dom) { this.dom.innerHTML = html; } return this; }, /** * Set the innerHTML of this element * @param {String} html The new HTML * @return {Ext.Element} this */ setHTML: function(html) { if(this.dom) { this.dom.innerHTML = html; } return this; }, /** * Returns the innerHTML of an Element or an empty string if the element's * dom no longer exists. */ getHTML: function() { return this.dom ? this.dom.innerHTML : ''; }, /** * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}. * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object * @return {Ext.Element} this */ hide: function() { this.setVisible(false); return this; }, /** * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}. * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object * @return {Ext.Element} this */ show: function() { this.setVisible(true); return this; }, /** * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property. * @param {Boolean} visible Whether the element is visible * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object * @return {Ext.Element} this */ setVisible: function(visible, animate) { var me = this, statics = me.self, mode = me.getVisibilityMode(); switch (mode) { case statics.VISIBILITY: me.removeCls(['x-hidden-display', 'x-hidden-offsets']); me[visible ? 'removeCls' : 'addCls']('x-hidden-visibility'); break; case statics.DISPLAY: me.removeCls(['x-hidden-visibility', 'x-hidden-offsets']); me[visible ? 'removeCls' : 'addCls']('x-hidden-display'); break; case statics.OFFSETS: me.removeCls(['x-hidden-visibility', 'x-hidden-display']); me[visible ? 'removeCls' : 'addCls']('x-hidden-offsets'); break; } return me; }, getVisibilityMode: function() { var statics = this.self, dom = this.dom, mode = statics.data(dom, 'visibilityMode'); if (mode === undefined) { statics.data(dom, 'visibilityMode', mode = statics.DISPLAY); } return mode; }, /** * Use this to change the visisbiliy mode between {@link #VISIBILITY}, {@link #DISPLAY} or {@link #OFFSETS}. */ setVisibilityMode: function(mode) { this.self.data(this.dom, 'visibilityMode', mode); return this; } }, function() { var AbstractElement = this; /** * @member Ext * @method get * @alias Ext.dom.AbstractElement#get */ Ext.get = function() { var El = Ext.dom.Element; return El.get.apply(El, arguments); }; this.addStatics({ Fly: new Ext.Class({ extend: AbstractElement, constructor: function(dom) { this.dom = dom; } }), _flyweights: {}, /** * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference * to this element - the dom node can be overwritten by other code. {@link Ext#fly} is alias for * {@link Ext.dom.AbstractElement#fly}. * * Use this to make one-time references to DOM elements which are not going to be accessed again either by * application code, or by Ext's classes. If accessing an element which will be processed regularly, then {@link * Ext#get Ext.get} will be more appropriate to take advantage of the caching provided by the Ext.dom.Element * class. * * @param {String/HTMLElement} el The dom node or id * @param {String} [named] Allows for creation of named reusable flyweights to prevent conflicts (e.g. * internally Ext uses "_global") * @return {Ext.dom.Element} The shared Element object (or null if no matching element was found) * @static */ fly: function(el, named) { var ret = null, _flyweights = AbstractElement._flyweights; named = named || '_global'; el = Ext.getDom(el); if (el) { ret = _flyweights[named] || (_flyweights[named] = new AbstractElement.Fly()); ret.dom = el; } return ret; } }); /** * @member Ext * @method fly * @alias Ext.dom.AbstractElement#fly */ Ext.fly = function() { return AbstractElement.fly.apply(AbstractElement, arguments); }; (function (proto) { /** * @method destroy * @member Ext.dom.AbstractElement * @alias Ext.dom.AbstractElement#remove */ proto.destroy = proto.remove; /** * @method getById * @member Ext.dom.AbstractElement * @alias Ext.dom.AbstractElement#get */ proto.getById = Ext.get; })(this.prototype); }); })();