2 * Ext JS Library 2.2.1
\r
3 * Copyright(c) 2006-2009, Ext JS, LLC.
\r
4 * licensing@extjs.com
\r
6 * http://extjs.com/license
\r
10 * @class Ext.Element
\r
11 * Represents an Element in the DOM.<br><br>
\r
15 var el = Ext.get("my-div");
\r
17 // by DOM element reference
\r
18 var el = Ext.get(myDivElement);
\r
20 * <b>Animations</b><br />
\r
21 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
\r
22 * should either be a boolean (true) or an object literal with animation options. Note that the supported Element animation
\r
23 * options are a subset of the {@link Ext.Fx} animation options specific to Fx effects. The Element animation options are:
\r
25 Option Default Description
\r
26 --------- -------- ---------------------------------------------
\r
27 duration .35 The duration of the animation in seconds
\r
28 easing easeOut The easing method
\r
29 callback none A function to execute when the anim completes
\r
30 scope this The scope (this) of the callback function
\r
32 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
\r
33 * manipulate the animation. Here's an example:
\r
35 var el = Ext.get("my-div");
\r
40 // default animation
\r
41 el.setWidth(100, true);
\r
43 // animation with some options set
\r
50 // using the "anim" property to get the Anim object
\r
56 el.setWidth(100, opt);
\r
58 if(opt.anim.isAnimated()){
\r
62 * <b> Composite (Collections of) Elements</b><br />
\r
63 * For working with collections of Elements, see {@link Ext.CompositeElement}
\r
64 * @constructor Create a new Element directly.
\r
65 * @param {String/HTMLElement} element
\r
66 * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).
\r
69 var D = Ext.lib.Dom;
\r
70 var E = Ext.lib.Event;
\r
71 var A = Ext.lib.Anim;
\r
73 // local style camelizing for speed
\r
75 var camelRe = /(-[a-z])/gi;
\r
76 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
\r
77 var view = document.defaultView;
\r
79 Ext.Element = function(element, forceNew){
\r
80 var dom = typeof element == "string" ?
\r
81 document.getElementById(element) : element;
\r
82 if(!dom){ // invalid id/element
\r
86 if(forceNew !== true && id && Ext.Element.cache[id]){ // element object already exists
\r
87 return Ext.Element.cache[id];
\r
97 * The DOM element ID
\r
100 this.id = id || Ext.id(dom);
\r
103 var El = Ext.Element;
\r
107 * The element's default display mode (defaults to "")
\r
110 originalDisplay : "",
\r
112 visibilityMode : 1,
\r
114 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
\r
117 defaultUnit : "px",
\r
119 * Sets the element's visibility mode. When setVisible() is called it
\r
120 * will use this to determine whether to set the visibility or the display property.
\r
121 * @param visMode Element.VISIBILITY or Element.DISPLAY
\r
122 * @return {Ext.Element} this
\r
124 setVisibilityMode : function(visMode){
\r
125 this.visibilityMode = visMode;
\r
129 * Convenience method for setVisibilityMode(Element.DISPLAY)
\r
130 * @param {String} display (optional) What to set display to when visible
\r
131 * @return {Ext.Element} this
\r
133 enableDisplayMode : function(display){
\r
134 this.setVisibilityMode(El.DISPLAY);
\r
135 if(typeof display != "undefined") this.originalDisplay = display;
\r
140 * Looks at this node and then at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
\r
141 * @param {String} selector The simple selector to test
\r
142 * @param {Number/Mixed} maxDepth (optional) The max depth to
\r
143 search as a number or element (defaults to 10 || document.body)
\r
144 * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
\r
145 * @return {HTMLElement} The matching DOM node (or null if no match was found)
\r
147 findParent : function(simpleSelector, maxDepth, returnEl){
\r
148 var p = this.dom, b = document.body, depth = 0, dq = Ext.DomQuery, stopEl;
\r
149 maxDepth = maxDepth || 50;
\r
150 if(typeof maxDepth != "number"){
\r
151 stopEl = Ext.getDom(maxDepth);
\r
154 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
\r
155 if(dq.is(p, simpleSelector)){
\r
156 return returnEl ? Ext.get(p) : p;
\r
166 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
\r
167 * @param {String} selector The simple selector to test
\r
168 * @param {Number/Mixed} maxDepth (optional) The max depth to
\r
169 search as a number or element (defaults to 10 || document.body)
\r
170 * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
\r
171 * @return {HTMLElement} The matching DOM node (or null if no match was found)
\r
173 findParentNode : function(simpleSelector, maxDepth, returnEl){
\r
174 var p = Ext.fly(this.dom.parentNode, '_internal');
\r
175 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
\r
179 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
\r
180 * This is a shortcut for findParentNode() that always returns an Ext.Element.
\r
181 * @param {String} selector The simple selector to test
\r
182 * @param {Number/Mixed} maxDepth (optional) The max depth to
\r
183 search as a number or element (defaults to 10 || document.body)
\r
184 * @return {Ext.Element} The matching DOM node (or null if no match was found)
\r
186 up : function(simpleSelector, maxDepth){
\r
187 return this.findParentNode(simpleSelector, maxDepth, true);
\r
193 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
\r
194 * @param {String} selector The simple selector to test
\r
195 * @return {Boolean} True if this element matches the selector, else false
\r
197 is : function(simpleSelector){
\r
198 return Ext.DomQuery.is(this.dom, simpleSelector);
\r
202 * Perform animation on this element.
\r
203 * @param {Object} args The animation control args
\r
204 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
\r
205 * @param {Function} onComplete (optional) Function to call when animation completes
\r
206 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
\r
207 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
\r
208 * @return {Ext.Element} this
\r
210 animate : function(args, duration, onComplete, easing, animType){
\r
211 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
\r
216 * @private Internal animation call
\r
218 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
\r
219 animType = animType || 'run';
\r
221 var anim = Ext.lib.Anim[animType](
\r
223 (opt.duration || defaultDur) || .35,
\r
224 (opt.easing || defaultEase) || 'easeOut',
\r
226 Ext.callback(cb, this);
\r
227 Ext.callback(opt.callback, opt.scope || this, [this, opt]);
\r
235 // private legacy anim prep
\r
236 preanim : function(a, i){
\r
237 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
\r
241 * Removes worthless text nodes
\r
242 * @param {Boolean} forceReclean (optional) By default the element
\r
243 * keeps track if it has been cleaned already so
\r
244 * you can call this over and over. However, if you update the element and
\r
245 * need to force a reclean, you can pass true.
\r
247 clean : function(forceReclean){
\r
248 if(this.isCleaned && forceReclean !== true){
\r
252 var d = this.dom, n = d.firstChild, ni = -1;
\r
254 var nx = n.nextSibling;
\r
255 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
\r
258 n.nodeIndex = ++ni;
\r
262 this.isCleaned = true;
\r
267 * Scrolls this element into view within the passed container.
\r
268 * @param {Mixed} container (optional) The container element to scroll (defaults to document.body). Should be a
\r
269 * string (id), dom node, or Ext.Element.
\r
270 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
\r
271 * @return {Ext.Element} this
\r
273 scrollIntoView : function(container, hscroll){
\r
274 var c = Ext.getDom(container) || Ext.getBody().dom;
\r
277 var o = this.getOffsetsTo(c),
\r
278 l = o[0] + c.scrollLeft,
\r
279 t = o[1] + c.scrollTop,
\r
280 b = t+el.offsetHeight,
\r
281 r = l+el.offsetWidth;
\r
283 var ch = c.clientHeight;
\r
284 var ct = parseInt(c.scrollTop, 10);
\r
285 var cl = parseInt(c.scrollLeft, 10);
\r
287 var cr = cl + c.clientWidth;
\r
289 if(el.offsetHeight > ch || t < ct){
\r
292 c.scrollTop = b-ch;
\r
294 c.scrollTop = c.scrollTop; // corrects IE, other browsers will ignore
\r
296 if(hscroll !== false){
\r
297 if(el.offsetWidth > c.clientWidth || l < cl){
\r
300 c.scrollLeft = r-c.clientWidth;
\r
302 c.scrollLeft = c.scrollLeft;
\r
308 scrollChildIntoView : function(child, hscroll){
\r
309 Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
\r
313 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
\r
314 * the new height may not be available immediately.
\r
315 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
\r
316 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
\r
317 * @param {Function} onComplete (optional) Function to call when animation completes
\r
318 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
\r
319 * @return {Ext.Element} this
\r
321 autoHeight : function(animate, duration, onComplete, easing){
\r
322 var oldHeight = this.getHeight();
\r
324 this.setHeight(1); // force clipping
\r
325 setTimeout(function(){
\r
326 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
\r
328 this.setHeight(height);
\r
330 if(typeof onComplete == "function"){
\r
334 this.setHeight(oldHeight); // restore original height
\r
335 this.setHeight(height, animate, duration, function(){
\r
337 if(typeof onComplete == "function") onComplete();
\r
338 }.createDelegate(this), easing);
\r
340 }.createDelegate(this), 0);
\r
345 * Returns true if this element is an ancestor of the passed element
\r
346 * @param {HTMLElement/String} el The element to check
\r
347 * @return {Boolean} True if this element is an ancestor of el, else false
\r
349 contains : function(el){
\r
350 if(!el){return false;}
\r
351 return D.isAncestor(this.dom, el.dom ? el.dom : el);
\r
355 * Checks whether the element is currently visible using both visibility and display properties.
\r
356 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
\r
357 * @return {Boolean} True if the element is currently visible, else false
\r
359 isVisible : function(deep) {
\r
360 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
\r
361 if(deep !== true || !vis){
\r
364 var p = this.dom.parentNode;
\r
365 while(p && p.tagName.toLowerCase() != "body"){
\r
366 if(!Ext.fly(p, '_isVisible').isVisible()){
\r
375 * Creates a {@link Ext.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
\r
376 * @param {String} selector The CSS selector
\r
377 * @param {Boolean} unique (optional) True to create a unique Ext.Element for each child (defaults to false, which creates a single shared flyweight object)
\r
378 * @return {CompositeElement/CompositeElementLite} The composite element
\r
380 select : function(selector, unique){
\r
381 return El.select(selector, unique, this.dom);
\r
385 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
\r
386 * @param {String} selector The CSS selector
\r
387 * @return {Array} An array of the matched nodes
\r
389 query : function(selector){
\r
390 return Ext.DomQuery.select(selector, this.dom);
\r
394 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
\r
395 * @param {String} selector The CSS selector
\r
396 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Ext.Element (defaults to false)
\r
397 * @return {HTMLElement/Ext.Element} The child Ext.Element (or DOM node if returnDom = true)
\r
399 child : function(selector, returnDom){
\r
400 var n = Ext.DomQuery.selectNode(selector, this.dom);
\r
401 return returnDom ? n : Ext.get(n);
\r
405 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
\r
406 * @param {String} selector The CSS selector
\r
407 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Ext.Element (defaults to false)
\r
408 * @return {HTMLElement/Ext.Element} The child Ext.Element (or DOM node if returnDom = true)
\r
410 down : function(selector, returnDom){
\r
411 var n = Ext.DomQuery.selectNode(" > " + selector, this.dom);
\r
412 return returnDom ? n : Ext.get(n);
\r
416 * Initializes a {@link Ext.dd.DD} drag drop object for this element.
\r
417 * @param {String} group The group the DD object is member of
\r
418 * @param {Object} config The DD config object
\r
419 * @param {Object} overrides An object containing methods to override/implement on the DD object
\r
420 * @return {Ext.dd.DD} The DD object
\r
422 initDD : function(group, config, overrides){
\r
423 var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
\r
424 return Ext.apply(dd, overrides);
\r
428 * Initializes a {@link Ext.dd.DDProxy} object for this element.
\r
429 * @param {String} group The group the DDProxy object is member of
\r
430 * @param {Object} config The DDProxy config object
\r
431 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
\r
432 * @return {Ext.dd.DDProxy} The DDProxy object
\r
434 initDDProxy : function(group, config, overrides){
\r
435 var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
\r
436 return Ext.apply(dd, overrides);
\r
440 * Initializes a {@link Ext.dd.DDTarget} object for this element.
\r
441 * @param {String} group The group the DDTarget object is member of
\r
442 * @param {Object} config The DDTarget config object
\r
443 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
\r
444 * @return {Ext.dd.DDTarget} The DDTarget object
\r
446 initDDTarget : function(group, config, overrides){
\r
447 var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
\r
448 return Ext.apply(dd, overrides);
\r
452 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
\r
453 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
\r
454 * @param {Boolean} visible Whether the element is visible
\r
455 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
\r
456 * @return {Ext.Element} this
\r
458 setVisible : function(visible, animate){
\r
459 if(!animate || !A){
\r
460 if(this.visibilityMode == El.DISPLAY){
\r
461 this.setDisplayed(visible);
\r
464 this.dom.style.visibility = visible ? "visible" : "hidden";
\r
467 // closure for composites
\r
468 var dom = this.dom;
\r
469 var visMode = this.visibilityMode;
\r
471 this.setOpacity(.01);
\r
472 this.setVisible(true);
\r
474 this.anim({opacity: { to: (visible?1:0) }},
\r
475 this.preanim(arguments, 1),
\r
476 null, .35, 'easeIn', function(){
\r
478 if(visMode == El.DISPLAY){
\r
479 dom.style.display = "none";
\r
481 dom.style.visibility = "hidden";
\r
483 Ext.get(dom).setOpacity(1);
\r
491 * Returns true if display is not "none"
\r
492 * @return {Boolean}
\r
494 isDisplayed : function() {
\r
495 return this.getStyle("display") != "none";
\r
499 * Toggles the element's visibility or display, depending on visibility mode.
\r
500 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
\r
501 * @return {Ext.Element} this
\r
503 toggle : function(animate){
\r
504 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
\r
509 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
\r
510 * @param {Mixed} value Boolean value to display the element using its default display, or a string to set the display directly.
\r
511 * @return {Ext.Element} this
\r
513 setDisplayed : function(value) {
\r
514 if(typeof value == "boolean"){
\r
515 value = value ? this.originalDisplay : "none";
\r
517 this.setStyle("display", value);
\r
522 * Tries to focus the element. Any exceptions are caught and ignored.
\r
523 * @return {Ext.Element} this
\r
525 focus : function() {
\r
533 * Tries to blur the element. Any exceptions are caught and ignored.
\r
534 * @return {Ext.Element} this
\r
536 blur : function() {
\r
544 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
\r
545 * @param {String/Array} className The CSS class to add, or an array of classes
\r
546 * @return {Ext.Element} this
\r
548 addClass : function(className){
\r
549 if(Ext.isArray(className)){
\r
550 for(var i = 0, len = className.length; i < len; i++) {
\r
551 this.addClass(className[i]);
\r
554 if(className && !this.hasClass(className)){
\r
555 this.dom.className = this.dom.className + " " + className;
\r
562 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
\r
563 * @param {String/Array} className The CSS class to add, or an array of classes
\r
564 * @return {Ext.Element} this
\r
566 radioClass : function(className){
\r
567 var siblings = this.dom.parentNode.childNodes;
\r
568 for(var i = 0; i < siblings.length; i++) {
\r
569 var s = siblings[i];
\r
570 if(s.nodeType == 1){
\r
571 Ext.get(s).removeClass(className);
\r
574 this.addClass(className);
\r
579 * Removes one or more CSS classes from the element.
\r
580 * @param {String/Array} className The CSS class to remove, or an array of classes
\r
581 * @return {Ext.Element} this
\r
583 removeClass : function(className){
\r
584 if(!className || !this.dom.className){
\r
587 if(Ext.isArray(className)){
\r
588 for(var i = 0, len = className.length; i < len; i++) {
\r
589 this.removeClass(className[i]);
\r
592 if(this.hasClass(className)){
\r
593 var re = this.classReCache[className];
\r
595 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
\r
596 this.classReCache[className] = re;
\r
598 this.dom.className =
\r
599 this.dom.className.replace(re, " ");
\r
609 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
\r
610 * @param {String} className The CSS class to toggle
\r
611 * @return {Ext.Element} this
\r
613 toggleClass : function(className){
\r
614 if(this.hasClass(className)){
\r
615 this.removeClass(className);
\r
617 this.addClass(className);
\r
623 * Checks if the specified CSS class exists on this element's DOM node.
\r
624 * @param {String} className The CSS class to check for
\r
625 * @return {Boolean} True if the class exists, else false
\r
627 hasClass : function(className){
\r
628 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
\r
632 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
\r
633 * @param {String} oldClassName The CSS class to replace
\r
634 * @param {String} newClassName The replacement CSS class
\r
635 * @return {Ext.Element} this
\r
637 replaceClass : function(oldClassName, newClassName){
\r
638 this.removeClass(oldClassName);
\r
639 this.addClass(newClassName);
\r
644 * Returns an object with properties matching the styles requested.
\r
645 * For example, el.getStyles('color', 'font-size', 'width') might return
\r
646 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
\r
647 * @param {String} style1 A style name
\r
648 * @param {String} style2 A style name
\r
649 * @param {String} etc.
\r
650 * @return {Object} The style object
\r
652 getStyles : function(){
\r
653 var a = arguments, len = a.length, r = {};
\r
654 for(var i = 0; i < len; i++){
\r
655 r[a[i]] = this.getStyle(a[i]);
\r
661 * Normalizes currentStyle and computedStyle.
\r
662 * @param {String} property The style property whose value is returned.
\r
663 * @return {String} The current value of the style property for this element.
\r
665 getStyle : function(){
\r
666 return view && view.getComputedStyle ?
\r
668 var el = this.dom, v, cs, camel;
\r
669 if(prop == 'float'){
\r
672 if(v = el.style[prop]){
\r
675 if(cs = view.getComputedStyle(el, "")){
\r
676 if(!(camel = propCache[prop])){
\r
677 camel = propCache[prop] = prop.replace(camelRe, camelFn);
\r
684 var el = this.dom, v, cs, camel;
\r
685 if(prop == 'opacity'){
\r
686 if(typeof el.style.filter == 'string'){
\r
687 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
\r
689 var fv = parseFloat(m[1]);
\r
691 return fv ? fv / 100 : 0;
\r
696 }else if(prop == 'float'){
\r
697 prop = "styleFloat";
\r
699 if(!(camel = propCache[prop])){
\r
700 camel = propCache[prop] = prop.replace(camelRe, camelFn);
\r
702 if(v = el.style[camel]){
\r
705 if(cs = el.currentStyle){
\r
713 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
\r
714 * @param {String/Object} property The style property to be set, or an object of multiple styles.
\r
715 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
\r
716 * @return {Ext.Element} this
\r
718 setStyle : function(prop, value){
\r
719 if(typeof prop == "string"){
\r
721 if(!(camel = propCache[prop])){
\r
722 camel = propCache[prop] = prop.replace(camelRe, camelFn);
\r
724 if(camel == 'opacity') {
\r
725 this.setOpacity(value);
\r
727 this.dom.style[camel] = value;
\r
730 for(var style in prop){
\r
731 if(typeof prop[style] != "function"){
\r
732 this.setStyle(style, prop[style]);
\r
740 * More flexible version of {@link #setStyle} for setting style properties.
\r
741 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
\r
742 * a function which returns such a specification.
\r
743 * @return {Ext.Element} this
\r
745 applyStyles : function(style){
\r
746 Ext.DomHelper.applyStyles(this.dom, style);
\r
751 * Gets the current X position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
\r
752 * @return {Number} The X position of the element
\r
755 return D.getX(this.dom);
\r
759 * Gets the current Y position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
\r
760 * @return {Number} The Y position of the element
\r
763 return D.getY(this.dom);
\r
767 * Gets the current position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
\r
768 * @return {Array} The XY position of the element
\r
770 getXY : function(){
\r
771 return D.getXY(this.dom);
\r
775 * Returns the offsets of this element from the passed element. Both element must be part of the DOM tree and not have display:none to have page coordinates.
\r
776 * @param {Mixed} element The element to get the offsets from.
\r
777 * @return {Array} The XY page offsets (e.g. [100, -200])
\r
779 getOffsetsTo : function(el){
\r
780 var o = this.getXY();
\r
781 var e = Ext.fly(el, '_internal').getXY();
\r
782 return [o[0]-e[0],o[1]-e[1]];
\r
786 * Sets the X position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
\r
787 * @param {Number} The X position of the element
\r
788 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
\r
789 * @return {Ext.Element} this
\r
791 setX : function(x, animate){
\r
792 if(!animate || !A){
\r
793 D.setX(this.dom, x);
\r
795 this.setXY([x, this.getY()], this.preanim(arguments, 1));
\r
801 * Sets the Y position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
\r
802 * @param {Number} The Y position of the element
\r
803 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
\r
804 * @return {Ext.Element} this
\r
806 setY : function(y, animate){
\r
807 if(!animate || !A){
\r
808 D.setY(this.dom, y);
\r
810 this.setXY([this.getX(), y], this.preanim(arguments, 1));
\r
816 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
\r
817 * @param {String} left The left CSS property value
\r
818 * @return {Ext.Element} this
\r
820 setLeft : function(left){
\r
821 this.setStyle("left", this.addUnits(left));
\r
826 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
\r
827 * @param {String} top The top CSS property value
\r
828 * @return {Ext.Element} this
\r
830 setTop : function(top){
\r
831 this.setStyle("top", this.addUnits(top));
\r
836 * Sets the element's CSS right style.
\r
837 * @param {String} right The right CSS property value
\r
838 * @return {Ext.Element} this
\r
840 setRight : function(right){
\r
841 this.setStyle("right", this.addUnits(right));
\r
846 * Sets the element's CSS bottom style.
\r
847 * @param {String} bottom The bottom CSS property value
\r
848 * @return {Ext.Element} this
\r
850 setBottom : function(bottom){
\r
851 this.setStyle("bottom", this.addUnits(bottom));
\r
856 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
\r
857 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
\r
858 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
\r
859 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
\r
860 * @return {Ext.Element} this
\r
862 setXY : function(pos, animate){
\r
863 if(!animate || !A){
\r
864 D.setXY(this.dom, pos);
\r
866 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
\r
872 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
\r
873 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
\r
874 * @param {Number} x X value for new position (coordinates are page-based)
\r
875 * @param {Number} y Y value for new position (coordinates are page-based)
\r
876 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
\r
877 * @return {Ext.Element} this
\r
879 setLocation : function(x, y, animate){
\r
880 this.setXY([x, y], this.preanim(arguments, 2));
\r
885 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
\r
886 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
\r
887 * @param {Number} x X value for new position (coordinates are page-based)
\r
888 * @param {Number} y Y value for new position (coordinates are page-based)
\r
889 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
\r
890 * @return {Ext.Element} this
\r
892 moveTo : function(x, y, animate){
\r
893 this.setXY([x, y], this.preanim(arguments, 2));
\r
898 * Returns the region of the given element.
\r
899 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
\r
900 * @return {Region} A Ext.lib.Region containing "top, left, bottom, right" member data.
\r
902 getRegion : function(){
\r
903 return D.getRegion(this.dom);
\r
907 * Returns the offset height of the element
\r
908 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
\r
909 * @return {Number} The element's height
\r
911 getHeight : function(contentHeight){
\r
912 var h = this.dom.offsetHeight || 0;
\r
913 h = contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
\r
914 return h < 0 ? 0 : h;
\r
918 * Returns the offset width of the element
\r
919 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
\r
920 * @return {Number} The element's width
\r
922 getWidth : function(contentWidth){
\r
923 var w = this.dom.offsetWidth || 0;
\r
924 w = contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
\r
925 return w < 0 ? 0 : w;
\r
929 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
\r
930 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
\r
931 * if a height has not been set using CSS.
\r
934 getComputedHeight : function(){
\r
935 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
\r
937 h = parseInt(this.getStyle('height'), 10) || 0;
\r
938 if(!this.isBorderBox()){
\r
939 h += this.getFrameWidth('tb');
\r
946 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
\r
947 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
\r
948 * if a width has not been set using CSS.
\r
951 getComputedWidth : function(){
\r
952 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
\r
954 w = parseInt(this.getStyle('width'), 10) || 0;
\r
955 if(!this.isBorderBox()){
\r
956 w += this.getFrameWidth('lr');
\r
963 * Returns the size of the element.
\r
964 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
\r
965 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
\r
967 getSize : function(contentSize){
\r
968 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
\r
971 getStyleSize : function(){
\r
972 var w, h, d = this.dom, s = d.style;
\r
973 if(s.width && s.width != 'auto'){
\r
974 w = parseInt(s.width, 10);
\r
975 if(Ext.isBorderBox){
\r
976 w -= this.getFrameWidth('lr');
\r
979 if(s.height && s.height != 'auto'){
\r
980 h = parseInt(s.height, 10);
\r
981 if(Ext.isBorderBox){
\r
982 h -= this.getFrameWidth('tb');
\r
985 return {width: w || this.getWidth(true), height: h || this.getHeight(true)};
\r
990 * Returns the width and height of the viewport.
\r
991 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
\r
993 getViewSize : function(){
\r
994 var d = this.dom, doc = document, aw = 0, ah = 0;
\r
995 if(d == doc || d == doc.body){
\r
996 return {width : D.getViewWidth(), height: D.getViewHeight()};
\r
999 width : d.clientWidth,
\r
1000 height: d.clientHeight
\r
1006 * Returns the value of the "value" attribute
\r
1007 * @param {Boolean} asNumber true to parse the value as a number
\r
1008 * @return {String/Number}
\r
1010 getValue : function(asNumber){
\r
1011 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
\r
1015 adjustWidth : function(width){
\r
1016 if(typeof width == "number"){
\r
1017 if(this.autoBoxAdjust && !this.isBorderBox()){
\r
1018 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
\r
1028 adjustHeight : function(height){
\r
1029 if(typeof height == "number"){
\r
1030 if(this.autoBoxAdjust && !this.isBorderBox()){
\r
1031 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
\r
1041 * Set the width of the element
\r
1042 * @param {Number} width The new width
\r
1043 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1044 * @return {Ext.Element} this
\r
1046 setWidth : function(width, animate){
\r
1047 width = this.adjustWidth(width);
\r
1048 if(!animate || !A){
\r
1049 this.dom.style.width = this.addUnits(width);
\r
1051 this.anim({width: {to: width}}, this.preanim(arguments, 1));
\r
1057 * Set the height of the element
\r
1058 * @param {Number} height The new height
\r
1059 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1060 * @return {Ext.Element} this
\r
1062 setHeight : function(height, animate){
\r
1063 height = this.adjustHeight(height);
\r
1064 if(!animate || !A){
\r
1065 this.dom.style.height = this.addUnits(height);
\r
1067 this.anim({height: {to: height}}, this.preanim(arguments, 1));
\r
1073 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
\r
1074 * @param {Number} width The new width
\r
1075 * @param {Number} height The new height
\r
1076 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1077 * @return {Ext.Element} this
\r
1079 setSize : function(width, height, animate){
\r
1080 if(typeof width == "object"){ // in case of object from getSize()
\r
1081 height = width.height; width = width.width;
\r
1083 width = this.adjustWidth(width); height = this.adjustHeight(height);
\r
1084 if(!animate || !A){
\r
1085 this.dom.style.width = this.addUnits(width);
\r
1086 this.dom.style.height = this.addUnits(height);
\r
1088 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
\r
1094 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
\r
1095 * @param {Number} x X value for new position (coordinates are page-based)
\r
1096 * @param {Number} y Y value for new position (coordinates are page-based)
\r
1097 * @param {Number} width The new width
\r
1098 * @param {Number} height The new height
\r
1099 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1100 * @return {Ext.Element} this
\r
1102 setBounds : function(x, y, width, height, animate){
\r
1103 if(!animate || !A){
\r
1104 this.setSize(width, height);
\r
1105 this.setLocation(x, y);
\r
1107 width = this.adjustWidth(width); height = this.adjustHeight(height);
\r
1108 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
\r
1109 this.preanim(arguments, 4), 'motion');
\r
1115 * Sets the element's position and size the specified region. If animation is true then width, height, x and y will be animated concurrently.
\r
1116 * @param {Ext.lib.Region} region The region to fill
\r
1117 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1118 * @return {Ext.Element} this
\r
1120 setRegion : function(region, animate){
\r
1121 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
\r
1126 * Appends an event handler to this element. The shorthand version {@link #on} is equivalent.
\r
1127 * @param {String} eventName The type of event to handle
\r
1128 * @param {Function} fn The handler function the event invokes. This function is passed
\r
1129 * the following parameters:<ul>
\r
1130 * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
\r
1131 * <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.
\r
1132 * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
\r
1133 * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
\r
1135 * @param {Object} scope (optional) The scope (The <tt>this</tt> reference) of the handler function. Defaults
\r
1136 * to this Element.
\r
1137 * @param {Object} options (optional) An object containing handler configuration properties.
\r
1138 * This may contain any of the following properties:<ul>
\r
1139 * <li>scope {Object} : The scope in which to execute the handler function. The handler function's "this" context.</li>
\r
1140 * <li>delegate {String} : A simple selector to filter the target or look for a descendant of the target</li>
\r
1141 * <li>stopEvent {Boolean} : True to stop the event. That is stop propagation, and prevent the default action.</li>
\r
1142 * <li>preventDefault {Boolean} : True to prevent the default action</li>
\r
1143 * <li>stopPropagation {Boolean} : True to prevent event propagation</li>
\r
1144 * <li>normalized {Boolean} : False to pass a browser event to the handler function instead of an Ext.EventObject</li>
\r
1145 * <li>delay {Number} : The number of milliseconds to delay the invocation of the handler after te event fires.</li>
\r
1146 * <li>single {Boolean} : True to add a handler to handle just the next firing of the event, and then remove itself.</li>
\r
1147 * <li>buffer {Number} : Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
\r
1148 * by the specified number of milliseconds. If the event fires again within that time, the original
\r
1149 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
\r
1152 * <b>Combining Options</b><br>
\r
1153 * In the following examples, the shorthand form {@link #on} is used rather than the more verbose
\r
1154 * addListener. The two are equivalent. Using the options argument, it is possible to combine different
\r
1155 * types of listeners:<br>
\r
1157 * A normalized, delayed, one-time listener that auto stops the event and adds a custom argument (forumId) to the
\r
1158 * options object. The options object is available as the third parameter in the handler function.<div style="margin: 5px 20px 20px;">
\r
1159 * Code:<pre><code>
\r
1160 el.on('click', this.onClick, this, {
\r
1165 });</code></pre></p>
\r
1167 * <b>Attaching multiple handlers in 1 call</b><br>
\r
1168 * The method also allows for a single argument to be passed which is a config object containing properties
\r
1169 * which specify multiple handlers.</p>
\r
1171 * Code:<pre><code></p>
\r
1179 fn: this.onMouseOver,
\r
1183 fn: this.onMouseOut,
\r
1188 * Or a shorthand syntax:<br>
\r
1189 * Code:<pre><code></p>
\r
1191 'click' : this.onClick,
\r
1192 'mouseover' : this.onMouseOver,
\r
1193 'mouseout' : this.onMouseOut,
\r
1197 addListener : function(eventName, fn, scope, options){
\r
1198 Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
\r
1202 * Removes an event handler from this element. The shorthand version {@link #un} is equivalent. Example:
\r
1204 el.removeListener('click', this.handlerFn);
\r
1206 el.un('click', this.handlerFn);
\r
1208 * @param {String} eventName the type of event to remove
\r
1209 * @param {Function} fn the method the event invokes
\r
1210 * @param {Object} scope (optional) The scope (The <tt>this</tt> reference) of the handler function. Defaults
\r
1211 * to this Element.
\r
1212 * @return {Ext.Element} this
\r
1214 removeListener : function(eventName, fn, scope){
\r
1215 Ext.EventManager.removeListener(this.dom, eventName, fn, scope || this);
\r
1220 * Removes all previous added listeners from this element
\r
1221 * @return {Ext.Element} this
\r
1223 removeAllListeners : function(){
\r
1224 Ext.EventManager.removeAll(this.dom);
\r
1229 * Create an event handler on this element such that when the event fires and is handled by this element,
\r
1230 * it will be relayed to another object (i.e., fired again as if it originated from that object instead).
\r
1231 * @param {String} eventName The type of event to relay
\r
1232 * @param {Object} object Any object that extends {@link Ext.util.Observable} that will provide the context
\r
1233 * for firing the relayed event
\r
1235 relayEvent : function(eventName, observable){
\r
1236 this.on(eventName, function(e){
\r
1237 observable.fireEvent(eventName, e);
\r
1242 * Set the opacity of the element
\r
1243 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
\r
1244 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1245 * @return {Ext.Element} this
\r
1247 setOpacity : function(opacity, animate){
\r
1248 if(!animate || !A){
\r
1249 var s = this.dom.style;
\r
1252 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
\r
1253 (opacity == 1 ? "" : " alpha(opacity=" + opacity * 100 + ")");
\r
1255 s.opacity = opacity;
\r
1258 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
\r
1264 * Gets the left X coordinate
\r
1265 * @param {Boolean} local True to get the local css position instead of page coordinate
\r
1266 * @return {Number}
\r
1268 getLeft : function(local){
\r
1270 return this.getX();
\r
1272 return parseInt(this.getStyle("left"), 10) || 0;
\r
1277 * Gets the right X coordinate of the element (element X position + element width)
\r
1278 * @param {Boolean} local True to get the local css position instead of page coordinate
\r
1279 * @return {Number}
\r
1281 getRight : function(local){
\r
1283 return this.getX() + this.getWidth();
\r
1285 return (this.getLeft(true) + this.getWidth()) || 0;
\r
1290 * Gets the top Y coordinate
\r
1291 * @param {Boolean} local True to get the local css position instead of page coordinate
\r
1292 * @return {Number}
\r
1294 getTop : function(local) {
\r
1296 return this.getY();
\r
1298 return parseInt(this.getStyle("top"), 10) || 0;
\r
1303 * Gets the bottom Y coordinate of the element (element Y position + element height)
\r
1304 * @param {Boolean} local True to get the local css position instead of page coordinate
\r
1305 * @return {Number}
\r
1307 getBottom : function(local){
\r
1309 return this.getY() + this.getHeight();
\r
1311 return (this.getTop(true) + this.getHeight()) || 0;
\r
1316 * Initializes positioning on this element. If a desired position is not passed, it will make the
\r
1317 * the element positioned relative IF it is not already positioned.
\r
1318 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
\r
1319 * @param {Number} zIndex (optional) The zIndex to apply
\r
1320 * @param {Number} x (optional) Set the page X position
\r
1321 * @param {Number} y (optional) Set the page Y position
\r
1323 position : function(pos, zIndex, x, y){
\r
1325 if(this.getStyle('position') == 'static'){
\r
1326 this.setStyle('position', 'relative');
\r
1329 this.setStyle("position", pos);
\r
1332 this.setStyle("z-index", zIndex);
\r
1334 if(x !== undefined && y !== undefined){
\r
1335 this.setXY([x, y]);
\r
1336 }else if(x !== undefined){
\r
1338 }else if(y !== undefined){
\r
1344 * Clear positioning back to the default when the document was loaded
\r
1345 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
\r
1346 * @return {Ext.Element} this
\r
1348 clearPositioning : function(value){
\r
1349 value = value ||'';
\r
1356 "position" : "static"
\r
1362 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
\r
1363 * snapshot before performing an update and then restoring the element.
\r
1364 * @return {Object}
\r
1366 getPositioning : function(){
\r
1367 var l = this.getStyle("left");
\r
1368 var t = this.getStyle("top");
\r
1370 "position" : this.getStyle("position"),
\r
1372 "right" : l ? "" : this.getStyle("right"),
\r
1374 "bottom" : t ? "" : this.getStyle("bottom"),
\r
1375 "z-index" : this.getStyle("z-index")
\r
1380 * Gets the width of the border(s) for the specified side(s)
\r
1381 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
\r
1382 * passing lr would get the border (l)eft width + the border (r)ight width.
\r
1383 * @return {Number} The width of the sides passed added together
\r
1385 getBorderWidth : function(side){
\r
1386 return this.addStyles(side, El.borders);
\r
1390 * Gets the width of the padding(s) for the specified side(s)
\r
1391 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
\r
1392 * passing lr would get the padding (l)eft + the padding (r)ight.
\r
1393 * @return {Number} The padding of the sides passed added together
\r
1395 getPadding : function(side){
\r
1396 return this.addStyles(side, El.paddings);
\r
1400 * Set positioning with an object returned by getPositioning().
\r
1401 * @param {Object} posCfg
\r
1402 * @return {Ext.Element} this
\r
1404 setPositioning : function(pc){
\r
1405 this.applyStyles(pc);
\r
1406 if(pc.right == "auto"){
\r
1407 this.dom.style.right = "";
\r
1409 if(pc.bottom == "auto"){
\r
1410 this.dom.style.bottom = "";
\r
1416 fixDisplay : function(){
\r
1417 if(this.getStyle("display") == "none"){
\r
1418 this.setStyle("visibility", "hidden");
\r
1419 this.setStyle("display", this.originalDisplay); // first try reverting to default
\r
1420 if(this.getStyle("display") == "none"){ // if that fails, default to block
\r
1421 this.setStyle("display", "block");
\r
1427 setOverflow : function(v){
\r
1428 if(v=='auto' && Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug
\r
1429 this.dom.style.overflow = 'hidden';
\r
1430 (function(){this.dom.style.overflow = 'auto';}).defer(1, this);
\r
1432 this.dom.style.overflow = v;
\r
1437 * Quick set left and top adding default units
\r
1438 * @param {String} left The left CSS property value
\r
1439 * @param {String} top The top CSS property value
\r
1440 * @return {Ext.Element} this
\r
1442 setLeftTop : function(left, top){
\r
1443 this.dom.style.left = this.addUnits(left);
\r
1444 this.dom.style.top = this.addUnits(top);
\r
1449 * Move this element relative to its current position.
\r
1450 * @param {String} direction Possible values are: "l" (or "left"), "r" (or "right"), "t" (or "top", or "up"), "b" (or "bottom", or "down").
\r
1451 * @param {Number} distance How far to move the element in pixels
\r
1452 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1453 * @return {Ext.Element} this
\r
1455 move : function(direction, distance, animate){
\r
1456 var xy = this.getXY();
\r
1457 direction = direction.toLowerCase();
\r
1458 switch(direction){
\r
1461 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
\r
1465 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
\r
1470 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
\r
1475 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
\r
1482 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
\r
1483 * @return {Ext.Element} this
\r
1485 clip : function(){
\r
1486 if(!this.isClipped){
\r
1487 this.isClipped = true;
\r
1488 this.originalClip = {
\r
1489 "o": this.getStyle("overflow"),
\r
1490 "x": this.getStyle("overflow-x"),
\r
1491 "y": this.getStyle("overflow-y")
\r
1493 this.setStyle("overflow", "hidden");
\r
1494 this.setStyle("overflow-x", "hidden");
\r
1495 this.setStyle("overflow-y", "hidden");
\r
1501 * Return clipping (overflow) to original clipping before clip() was called
\r
1502 * @return {Ext.Element} this
\r
1504 unclip : function(){
\r
1505 if(this.isClipped){
\r
1506 this.isClipped = false;
\r
1507 var o = this.originalClip;
\r
1508 if(o.o){this.setStyle("overflow", o.o);}
\r
1509 if(o.x){this.setStyle("overflow-x", o.x);}
\r
1510 if(o.y){this.setStyle("overflow-y", o.y);}
\r
1517 * Gets the x,y coordinates specified by the anchor position on the element.
\r
1518 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo}
\r
1519 * for details on supported anchor positions.
\r
1520 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead
\r
1521 * of page coordinates
\r
1522 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
\r
1523 * {width: (target width), height: (target height)} (defaults to the element's current size)
\r
1524 * @return {Array} [x, y] An array containing the element's x and y coordinates
\r
1526 getAnchorXY : function(anchor, local, s){
\r
1527 //Passing a different size is useful for pre-calculating anchors,
\r
1528 //especially for anchored animations that change the el size.
\r
1530 var w, h, vp = false;
\r
1533 if(d == document.body || d == document){
\r
1535 w = D.getViewWidth(); h = D.getViewHeight();
\r
1537 w = this.getWidth(); h = this.getHeight();
\r
1540 w = s.width; h = s.height;
\r
1542 var x = 0, y = 0, r = Math.round;
\r
1543 switch((anchor || "tl").toLowerCase()){
\r
1581 if(local === true){
\r
1585 var sc = this.getScroll();
\r
1586 return [x + sc.left, y + sc.top];
\r
1588 //Add the element's offset xy
\r
1589 var o = this.getXY();
\r
1590 return [x+o[0], y+o[1]];
\r
1594 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
\r
1595 * supported position values.
\r
1596 * @param {Mixed} element The element to align to.
\r
1597 * @param {String} position The position to align to.
\r
1598 * @param {Array} offsets (optional) Offset the positioning by [x, y]
\r
1599 * @return {Array} [x, y]
\r
1601 getAlignToXY : function(el, p, o){
\r
1603 if(!el || !el.dom){
\r
1604 throw "Element.alignToXY with an element that doesn't exist";
\r
1607 var c = false; //constrain to viewport
\r
1608 var p1 = "", p2 = "";
\r
1613 }else if(p == "?"){
\r
1615 }else if(p.indexOf("-") == -1){
\r
1618 p = p.toLowerCase();
\r
1619 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
\r
1621 throw "Element.alignTo with an invalid alignment " + p;
\r
1623 p1 = m[1]; p2 = m[2]; c = !!m[3];
\r
1625 //Subtract the aligned el's internal xy from the target's offset xy
\r
1626 //plus custom offset to get the aligned el's new offset xy
\r
1627 var a1 = this.getAnchorXY(p1, true);
\r
1628 var a2 = el.getAnchorXY(p2, false);
\r
1630 var x = a2[0] - a1[0] + o[0];
\r
1631 var y = a2[1] - a1[1] + o[1];
\r
1634 //constrain the aligned el to viewport if necessary
\r
1635 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
\r
1636 // 5px of margin for ie
\r
1637 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
\r
1639 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
\r
1640 //perpendicular to the vp border, allow the aligned el to slide on that border,
\r
1641 //otherwise swap the aligned el to the opposite border of the target.
\r
1642 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
\r
1643 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
\r
1644 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
\r
1645 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
\r
1647 var doc = document;
\r
1648 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
\r
1649 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
\r
1651 if((x+w) > dw + scrollX){
\r
1652 x = swapX ? r.left-w : dw+scrollX-w;
\r
1655 x = swapX ? r.right : scrollX;
\r
1657 if((y+h) > dh + scrollY){
\r
1658 y = swapY ? r.top-h : dh+scrollY-h;
\r
1661 y = swapY ? r.bottom : scrollY;
\r
1668 getConstrainToXY : function(){
\r
1669 var os = {top:0, left:0, bottom:0, right: 0};
\r
1671 return function(el, local, offsets, proposedXY){
\r
1673 offsets = offsets ? Ext.applyIf(offsets, os) : os;
\r
1675 var vw, vh, vx = 0, vy = 0;
\r
1676 if(el.dom == document.body || el.dom == document){
\r
1677 vw = Ext.lib.Dom.getViewWidth();
\r
1678 vh = Ext.lib.Dom.getViewHeight();
\r
1680 vw = el.dom.clientWidth;
\r
1681 vh = el.dom.clientHeight;
\r
1683 var vxy = el.getXY();
\r
1689 var s = el.getScroll();
\r
1691 vx += offsets.left + s.left;
\r
1692 vy += offsets.top + s.top;
\r
1694 vw -= offsets.right;
\r
1695 vh -= offsets.bottom;
\r
1700 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
\r
1701 var x = xy[0], y = xy[1];
\r
1702 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
\r
1704 // only move it if it needs it
\r
1705 var moved = false;
\r
1707 // first validate right/bottom
\r
1716 // then make sure top/left isn't negative
\r
1725 return moved ? [x, y] : false;
\r
1730 adjustForConstraints : function(xy, parent, offsets){
\r
1731 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
\r
1735 * Aligns this element with another element relative to the specified anchor points. If the other element is the
\r
1736 * document it aligns it to the viewport.
\r
1737 * The position parameter is optional, and can be specified in any one of the following formats:
\r
1739 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
\r
1740 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
\r
1741 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
\r
1742 * deprecated in favor of the newer two anchor syntax below</i>.</li>
\r
1743 * <li><b>Two anchors</b>: If two values from the table below are passed separated by a dash, the first value is used as the
\r
1744 * element's anchor point, and the second value is used as the target's anchor point.</li>
\r
1746 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
\r
1747 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
\r
1748 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
\r
1749 * that specified in order to enforce the viewport constraints.
\r
1750 * Following are all of the supported anchor positions:
\r
1753 ----- -----------------------------
\r
1754 tl The top left corner (default)
\r
1755 t The center of the top edge
\r
1756 tr The top right corner
\r
1757 l The center of the left edge
\r
1758 c In the center of the element
\r
1759 r The center of the right edge
\r
1760 bl The bottom left corner
\r
1761 b The center of the bottom edge
\r
1762 br The bottom right corner
\r
1766 // align el to other-el using the default positioning ("tl-bl", non-constrained)
\r
1767 el.alignTo("other-el");
\r
1769 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
\r
1770 el.alignTo("other-el", "tr?");
\r
1772 // align the bottom right corner of el with the center left edge of other-el
\r
1773 el.alignTo("other-el", "br-l?");
\r
1775 // align the center of el with the bottom left corner of other-el and
\r
1776 // adjust the x position by -6 pixels (and the y position by 0)
\r
1777 el.alignTo("other-el", "c-bl", [-6, 0]);
\r
1779 * @param {Mixed} element The element to align to.
\r
1780 * @param {String} position The position to align to.
\r
1781 * @param {Array} offsets (optional) Offset the positioning by [x, y]
\r
1782 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1783 * @return {Ext.Element} this
\r
1785 alignTo : function(element, position, offsets, animate){
\r
1786 var xy = this.getAlignToXY(element, position, offsets);
\r
1787 this.setXY(xy, this.preanim(arguments, 3));
\r
1792 * Anchors an element to another element and realigns it when the window is resized.
\r
1793 * @param {Mixed} element The element to align to.
\r
1794 * @param {String} position The position to align to.
\r
1795 * @param {Array} offsets (optional) Offset the positioning by [x, y]
\r
1796 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
\r
1797 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
\r
1798 * is a number, it is used as the buffer delay (defaults to 50ms).
\r
1799 * @param {Function} callback The function to call after the animation finishes
\r
1800 * @return {Ext.Element} this
\r
1802 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
\r
1803 var action = function(){
\r
1804 this.alignTo(el, alignment, offsets, animate);
\r
1805 Ext.callback(callback, this);
\r
1807 Ext.EventManager.onWindowResize(action, this);
\r
1808 var tm = typeof monitorScroll;
\r
1809 if(tm != 'undefined'){
\r
1810 Ext.EventManager.on(window, 'scroll', action, this,
\r
1811 {buffer: tm == 'number' ? monitorScroll : 50});
\r
1813 action.call(this); // align immediately
\r
1817 * Clears any opacity settings from this element. Required in some cases for IE.
\r
1818 * @return {Ext.Element} this
\r
1820 clearOpacity : function(){
\r
1821 if (window.ActiveXObject) {
\r
1822 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
\r
1823 this.dom.style.filter = "";
\r
1826 this.dom.style.opacity = "";
\r
1827 this.dom.style["-moz-opacity"] = "";
\r
1828 this.dom.style["-khtml-opacity"] = "";
\r
1834 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
\r
1835 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1836 * @return {Ext.Element} this
\r
1838 hide : function(animate){
\r
1839 this.setVisible(false, this.preanim(arguments, 0));
\r
1844 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
\r
1845 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
1846 * @return {Ext.Element} this
\r
1848 show : function(animate){
\r
1849 this.setVisible(true, this.preanim(arguments, 0));
\r
1854 * @private Test if size has a unit, otherwise appends the default
\r
1856 addUnits : function(size){
\r
1857 return Ext.Element.addUnits(size, this.defaultUnit);
\r
1861 * Update the innerHTML of this element, optionally searching for and processing scripts
\r
1862 * @param {String} html The new HTML
\r
1863 * @param {Boolean} loadScripts (optional) True to look for and process scripts (defaults to false)
\r
1864 * @param {Function} callback (optional) For async script loading you can be notified when the update completes
\r
1865 * @return {Ext.Element} this
\r
1867 update : function(html, loadScripts, callback){
\r
1868 if(typeof html == "undefined"){
\r
1871 if(loadScripts !== true){
\r
1872 this.dom.innerHTML = html;
\r
1873 if(typeof callback == "function"){
\r
1878 var id = Ext.id();
\r
1879 var dom = this.dom;
\r
1881 html += '<span id="' + id + '"></span>';
\r
1883 E.onAvailable(id, function(){
\r
1884 var hd = document.getElementsByTagName("head")[0];
\r
1885 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
\r
1886 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
\r
1887 var typeRe = /\stype=([\'\"])(.*?)\1/i;
\r
1890 while(match = re.exec(html)){
\r
1891 var attrs = match[1];
\r
1892 var srcMatch = attrs ? attrs.match(srcRe) : false;
\r
1893 if(srcMatch && srcMatch[2]){
\r
1894 var s = document.createElement("script");
\r
1895 s.src = srcMatch[2];
\r
1896 var typeMatch = attrs.match(typeRe);
\r
1897 if(typeMatch && typeMatch[2]){
\r
1898 s.type = typeMatch[2];
\r
1900 hd.appendChild(s);
\r
1901 }else if(match[2] && match[2].length > 0){
\r
1902 if(window.execScript) {
\r
1903 window.execScript(match[2]);
\r
1905 window.eval(match[2]);
\r
1909 var el = document.getElementById(id);
\r
1910 if(el){Ext.removeNode(el);}
\r
1911 if(typeof callback == "function"){
\r
1915 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
\r
1920 * Direct access to the Updater {@link Ext.Updater#update} method. The method takes the same object
\r
1921 * parameter as {@link Ext.Updater#update}
\r
1922 * @return {Ext.Element} this
\r
1924 load : function(){
\r
1925 var um = this.getUpdater();
\r
1926 um.update.apply(um, arguments);
\r
1931 * Gets this element's Updater
\r
1932 * @return {Ext.Updater} The Updater
\r
1934 getUpdater : function(){
\r
1935 if(!this.updateManager){
\r
1936 this.updateManager = new Ext.Updater(this);
\r
1938 return this.updateManager;
\r
1942 * Disables text selection for this element (normalized across browsers)
\r
1943 * @return {Ext.Element} this
\r
1945 unselectable : function(){
\r
1946 this.dom.unselectable = "on";
\r
1947 this.swallowEvent("selectstart", true);
\r
1948 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
\r
1949 this.addClass("x-unselectable");
\r
1954 * Calculates the x, y to center this element on the screen
\r
1955 * @return {Array} The x, y values [x, y]
\r
1957 getCenterXY : function(){
\r
1958 return this.getAlignToXY(document, 'c-c');
\r
1962 * Centers the Element in either the viewport, or another Element.
\r
1963 * @param {Mixed} centerIn (optional) The element in which to center the element.
\r
1965 center : function(centerIn){
\r
1966 this.alignTo(centerIn || document, 'c-c');
\r
1971 * Tests various css rules/browsers to determine if this element uses a border box
\r
1972 * @return {Boolean}
\r
1974 isBorderBox : function(){
\r
1975 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Ext.isBorderBox;
\r
1979 * Return a box {x, y, width, height} that can be used to set another elements
\r
1980 * size/location to match this element.
\r
1981 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
\r
1982 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
\r
1983 * @return {Object} box An object in the format {x, y, width, height}
\r
1985 getBox : function(contentBox, local){
\r
1988 xy = this.getXY();
\r
1990 var left = parseInt(this.getStyle("left"), 10) || 0;
\r
1991 var top = parseInt(this.getStyle("top"), 10) || 0;
\r
1994 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
\r
1996 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
\r
1998 var l = this.getBorderWidth("l")+this.getPadding("l");
\r
1999 var r = this.getBorderWidth("r")+this.getPadding("r");
\r
2000 var t = this.getBorderWidth("t")+this.getPadding("t");
\r
2001 var b = this.getBorderWidth("b")+this.getPadding("b");
\r
2002 bx = {x: xy[0]+l, y: xy[1]+t, 0: xy[0]+l, 1: xy[1]+t, width: w-(l+r), height: h-(t+b)};
\r
2004 bx.right = bx.x + bx.width;
\r
2005 bx.bottom = bx.y + bx.height;
\r
2010 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
\r
2011 for more information about the sides.
\r
2012 * @param {String} sides
\r
2013 * @return {Number}
\r
2015 getFrameWidth : function(sides, onlyContentBox){
\r
2016 return onlyContentBox && Ext.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
\r
2020 * Sets the element's box. Use getBox() on another element to get a box obj. If animate is true then width, height, x and y will be animated concurrently.
\r
2021 * @param {Object} box The box to fill {x, y, width, height}
\r
2022 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
\r
2023 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
2024 * @return {Ext.Element} this
\r
2026 setBox : function(box, adjust, animate){
\r
2027 var w = box.width, h = box.height;
\r
2028 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
\r
2029 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
\r
2030 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
\r
2032 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
\r
2037 * Forces the browser to repaint this element
\r
2038 * @return {Ext.Element} this
\r
2040 repaint : function(){
\r
2041 var dom = this.dom;
\r
2042 this.addClass("x-repaint");
\r
2043 setTimeout(function(){
\r
2044 Ext.get(dom).removeClass("x-repaint");
\r
2050 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
\r
2051 * then it returns the calculated width of the sides (see getPadding)
\r
2052 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
\r
2053 * @return {Object/Number}
\r
2055 getMargins : function(side){
\r
2058 top: parseInt(this.getStyle("margin-top"), 10) || 0,
\r
2059 left: parseInt(this.getStyle("margin-left"), 10) || 0,
\r
2060 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
\r
2061 right: parseInt(this.getStyle("margin-right"), 10) || 0
\r
2064 return this.addStyles(side, El.margins);
\r
2069 addStyles : function(sides, styles){
\r
2070 var val = 0, v, w;
\r
2071 for(var i = 0, len = sides.length; i < len; i++){
\r
2072 v = this.getStyle(styles[sides.charAt(i)]);
\r
2074 w = parseInt(v, 10);
\r
2075 if(w){ val += (w >= 0 ? w : -1 * w); }
\r
2082 * Creates a proxy element of this element
\r
2083 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
\r
2084 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
\r
2085 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
\r
2086 * @return {Ext.Element} The new proxy element
\r
2088 createProxy : function(config, renderTo, matchBox){
\r
2089 config = typeof config == "object" ?
\r
2090 config : {tag : "div", cls: config};
\r
2094 proxy = Ext.DomHelper.append(renderTo, config, true);
\r
2096 proxy = Ext.DomHelper.insertBefore(this.dom, config, true);
\r
2099 proxy.setBox(this.getBox());
\r
2105 * Puts a mask over this element to disable user interaction. Requires core.css.
\r
2106 * This method can only be applied to elements which accept child nodes.
\r
2107 * @param {String} msg (optional) A message to display in the mask
\r
2108 * @param {String} msgCls (optional) A css class to apply to the msg element
\r
2109 * @return {Element} The mask element
\r
2111 mask : function(msg, msgCls){
\r
2112 if(this.getStyle("position") == "static"){
\r
2113 this.addClass("x-masked-relative");
\r
2115 if(this._maskMsg){
\r
2116 this._maskMsg.remove();
\r
2119 this._mask.remove();
\r
2122 this._mask = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask"}, true);
\r
2124 this.addClass("x-masked");
\r
2125 this._mask.setDisplayed(true);
\r
2126 if(typeof msg == 'string'){
\r
2127 this._maskMsg = Ext.DomHelper.append(this.dom, {cls:"ext-el-mask-msg", cn:{tag:'div'}}, true);
\r
2128 var mm = this._maskMsg;
\r
2129 mm.dom.className = msgCls ? "ext-el-mask-msg " + msgCls : "ext-el-mask-msg";
\r
2130 mm.dom.firstChild.innerHTML = msg;
\r
2131 mm.setDisplayed(true);
\r
2134 if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
\r
2135 this._mask.setSize(this.getWidth(), this.getHeight());
\r
2137 return this._mask;
\r
2141 * Removes a previously applied mask.
\r
2143 unmask : function(){
\r
2145 if(this._maskMsg){
\r
2146 this._maskMsg.remove();
\r
2147 delete this._maskMsg;
\r
2149 this._mask.remove();
\r
2150 delete this._mask;
\r
2152 this.removeClass(["x-masked", "x-masked-relative"]);
\r
2156 * Returns true if this element is masked
\r
2157 * @return {Boolean}
\r
2159 isMasked : function(){
\r
2160 return this._mask && this._mask.isVisible();
\r
2164 * Creates an iframe shim for this element to keep selects and other windowed objects from
\r
2165 * showing through.
\r
2166 * @return {Ext.Element} The new shim element
\r
2168 createShim : function(){
\r
2169 var el = document.createElement('iframe');
\r
2170 el.frameBorder = '0';
\r
2171 el.className = 'ext-shim';
\r
2172 if(Ext.isIE && Ext.isSecure){
\r
2173 el.src = Ext.SSL_SECURE_URL;
\r
2175 var shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
\r
2176 shim.autoBoxAdjust = false;
\r
2181 * Removes this element from the DOM and deletes it from the cache
\r
2183 remove : function(){
\r
2184 Ext.removeNode(this.dom);
\r
2185 delete El.cache[this.dom.id];
\r
2189 * Sets up event handlers to call the passed functions when the mouse is over this element. Automatically
\r
2190 * filters child element mouse events.
\r
2191 * @param {Function} overFn
\r
2192 * @param {Function} outFn
\r
2193 * @param {Object} scope (optional)
\r
2194 * @return {Ext.Element} this
\r
2196 hover : function(overFn, outFn, scope){
\r
2197 var preOverFn = function(e){
\r
2198 if(!e.within(this, true)){
\r
2199 overFn.apply(scope || this, arguments);
\r
2202 var preOutFn = function(e){
\r
2203 if(!e.within(this, true)){
\r
2204 outFn.apply(scope || this, arguments);
\r
2207 this.on("mouseover", preOverFn, this.dom);
\r
2208 this.on("mouseout", preOutFn, this.dom);
\r
2213 * Sets up event handlers to add and remove a css class when the mouse is over this element
\r
2214 * @param {String} className
\r
2215 * @return {Ext.Element} this
\r
2217 addClassOnOver : function(className){
\r
2220 Ext.fly(this, '_internal').addClass(className);
\r
2223 Ext.fly(this, '_internal').removeClass(className);
\r
2230 * Sets up event handlers to add and remove a css class when this element has the focus
\r
2231 * @param {String} className
\r
2232 * @return {Ext.Element} this
\r
2234 addClassOnFocus : function(className){
\r
2235 this.on("focus", function(){
\r
2236 Ext.fly(this, '_internal').addClass(className);
\r
2238 this.on("blur", function(){
\r
2239 Ext.fly(this, '_internal').removeClass(className);
\r
2244 * Sets up event handlers to add and remove a css class when the mouse is down and then up on this element (a click effect)
\r
2245 * @param {String} className
\r
2246 * @return {Ext.Element} this
\r
2248 addClassOnClick : function(className){
\r
2249 var dom = this.dom;
\r
2250 this.on("mousedown", function(){
\r
2251 Ext.fly(dom, '_internal').addClass(className);
\r
2252 var d = Ext.getDoc();
\r
2253 var fn = function(){
\r
2254 Ext.fly(dom, '_internal').removeClass(className);
\r
2255 d.removeListener("mouseup", fn);
\r
2257 d.on("mouseup", fn);
\r
2263 * Stops the specified event(s) from bubbling and optionally prevents the default action
\r
2264 * @param {String/Array} eventName an event / array of events to stop from bubbling
\r
2265 * @param {Boolean} preventDefault (optional) true to prevent the default action too
\r
2266 * @return {Ext.Element} this
\r
2268 swallowEvent : function(eventName, preventDefault){
\r
2269 var fn = function(e){
\r
2270 e.stopPropagation();
\r
2271 if(preventDefault){
\r
2272 e.preventDefault();
\r
2275 if(Ext.isArray(eventName)){
\r
2276 for(var i = 0, len = eventName.length; i < len; i++){
\r
2277 this.on(eventName[i], fn);
\r
2281 this.on(eventName, fn);
\r
2286 * Gets the parent node for this element, optionally chaining up trying to match a selector
\r
2287 * @param {String} selector (optional) Find a parent node that matches the passed simple selector
\r
2288 * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
\r
2289 * @return {Ext.Element/HTMLElement} The parent node or null
\r
2291 parent : function(selector, returnDom){
\r
2292 return this.matchNode('parentNode', 'parentNode', selector, returnDom);
\r
2296 * Gets the next sibling, skipping text nodes
\r
2297 * @param {String} selector (optional) Find the next sibling that matches the passed simple selector
\r
2298 * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
\r
2299 * @return {Ext.Element/HTMLElement} The next sibling or null
\r
2301 next : function(selector, returnDom){
\r
2302 return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
\r
2306 * Gets the previous sibling, skipping text nodes
\r
2307 * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector
\r
2308 * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
\r
2309 * @return {Ext.Element/HTMLElement} The previous sibling or null
\r
2311 prev : function(selector, returnDom){
\r
2312 return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
\r
2317 * Gets the first child, skipping text nodes
\r
2318 * @param {String} selector (optional) Find the next sibling that matches the passed simple selector
\r
2319 * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
\r
2320 * @return {Ext.Element/HTMLElement} The first child or null
\r
2322 first : function(selector, returnDom){
\r
2323 return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
\r
2327 * Gets the last child, skipping text nodes
\r
2328 * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector
\r
2329 * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
\r
2330 * @return {Ext.Element/HTMLElement} The last child or null
\r
2332 last : function(selector, returnDom){
\r
2333 return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
\r
2336 matchNode : function(dir, start, selector, returnDom){
\r
2337 var n = this.dom[start];
\r
2339 if(n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))){
\r
2340 return !returnDom ? Ext.get(n) : n;
\r
2348 * Appends the passed element(s) to this element
\r
2349 * @param {String/HTMLElement/Array/Element/CompositeElement} el
\r
2350 * @return {Ext.Element} this
\r
2352 appendChild: function(el){
\r
2354 el.appendTo(this);
\r
2359 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
\r
2360 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
\r
2361 * automatically generated with the specified attributes.
\r
2362 * @param {HTMLElement} insertBefore (optional) a child element of this element
\r
2363 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
\r
2364 * @return {Ext.Element} The new child element
\r
2366 createChild: function(config, insertBefore, returnDom){
\r
2367 config = config || {tag:'div'};
\r
2369 return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
\r
2371 return Ext.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
\r
2375 * Appends this element to the passed element
\r
2376 * @param {Mixed} el The new parent element
\r
2377 * @return {Ext.Element} this
\r
2379 appendTo: function(el){
\r
2380 el = Ext.getDom(el);
\r
2381 el.appendChild(this.dom);
\r
2386 * Inserts this element before the passed element in the DOM
\r
2387 * @param {Mixed} el The element before which this element will be inserted
\r
2388 * @return {Ext.Element} this
\r
2390 insertBefore: function(el){
\r
2391 el = Ext.getDom(el);
\r
2392 el.parentNode.insertBefore(this.dom, el);
\r
2397 * Inserts this element after the passed element in the DOM
\r
2398 * @param {Mixed} el The element to insert after
\r
2399 * @return {Ext.Element} this
\r
2401 insertAfter: function(el){
\r
2402 el = Ext.getDom(el);
\r
2403 el.parentNode.insertBefore(this.dom, el.nextSibling);
\r
2408 * Inserts (or creates) an element (or DomHelper config) as the first child of this element
\r
2409 * @param {Mixed/Object} el The id or element to insert or a DomHelper config to create and insert
\r
2410 * @return {Ext.Element} The new child
\r
2412 insertFirst: function(el, returnDom){
\r
2414 if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config
\r
2415 return this.createChild(el, this.dom.firstChild, returnDom);
\r
2417 el = Ext.getDom(el);
\r
2418 this.dom.insertBefore(el, this.dom.firstChild);
\r
2419 return !returnDom ? Ext.get(el) : el;
\r
2424 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
\r
2425 * @param {Mixed/Object/Array} el The id, element to insert or a DomHelper config to create and insert *or* an array of any of those.
\r
2426 * @param {String} where (optional) 'before' or 'after' defaults to before
\r
2427 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Ext.Element
\r
2428 * @return {Ext.Element} the inserted Element
\r
2430 insertSibling: function(el, where, returnDom){
\r
2432 if(Ext.isArray(el)){
\r
2433 for(var i = 0, len = el.length; i < len; i++){
\r
2434 rt = this.insertSibling(el[i], where, returnDom);
\r
2438 where = where ? where.toLowerCase() : 'before';
\r
2440 var refNode = where == 'before' ? this.dom : this.dom.nextSibling;
\r
2442 if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config
\r
2443 if(where == 'after' && !this.dom.nextSibling){
\r
2444 rt = Ext.DomHelper.append(this.dom.parentNode, el, !returnDom);
\r
2446 rt = Ext.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
\r
2450 rt = this.dom.parentNode.insertBefore(Ext.getDom(el), refNode);
\r
2459 * Creates and wraps this element with another element
\r
2460 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
\r
2461 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Ext.Element
\r
2462 * @return {HTMLElement/Element} The newly created wrapper element
\r
2464 wrap: function(config, returnDom){
\r
2466 config = {tag: "div"};
\r
2468 var newEl = Ext.DomHelper.insertBefore(this.dom, config, !returnDom);
\r
2469 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
\r
2474 * Replaces the passed element with this element
\r
2475 * @param {Mixed} el The element to replace
\r
2476 * @return {Ext.Element} this
\r
2478 replace: function(el){
\r
2480 this.insertBefore(el);
\r
2486 * Replaces this element with the passed element
\r
2487 * @param {Mixed/Object} el The new element or a DomHelper config of an element to create
\r
2488 * @return {Ext.Element} this
\r
2490 replaceWith: function(el){
\r
2491 if(typeof el == 'object' && !el.nodeType && !el.dom){ // dh config
\r
2492 el = this.insertSibling(el, 'before');
\r
2494 el = Ext.getDom(el);
\r
2495 this.dom.parentNode.insertBefore(el, this.dom);
\r
2497 El.uncache(this.id);
\r
2498 Ext.removeNode(this.dom);
\r
2500 this.id = Ext.id(el);
\r
2501 El.cache[this.id] = this;
\r
2506 * Inserts an html fragment into this element
\r
2507 * @param {String} where Where to insert the html in relation to this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
\r
2508 * @param {String} html The HTML fragment
\r
2509 * @param {Boolean} returnEl (optional) True to return an Ext.Element (defaults to false)
\r
2510 * @return {HTMLElement/Ext.Element} The inserted node (or nearest related if more than 1 inserted)
\r
2512 insertHtml : function(where, html, returnEl){
\r
2513 var el = Ext.DomHelper.insertHtml(where, this.dom, html);
\r
2514 return returnEl ? Ext.get(el) : el;
\r
2518 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
\r
2519 * @param {Object} o The object with the attributes
\r
2520 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
\r
2521 * @return {Ext.Element} this
\r
2523 set : function(o, useSet){
\r
2524 var el = this.dom;
\r
2525 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
\r
2526 for(var attr in o){
\r
2527 if(attr == "style" || typeof o[attr] == "function") continue;
\r
2529 el.className = o["cls"];
\r
2530 }else if(o.hasOwnProperty(attr)){
\r
2531 if(useSet) el.setAttribute(attr, o[attr]);
\r
2532 else el[attr] = o[attr];
\r
2536 Ext.DomHelper.applyStyles(el, o.style);
\r
2542 * Convenience method for constructing a KeyMap
\r
2543 * @param {Number/Array/Object/String} key Either a string with the keys to listen for, the numeric key code, array of key codes or an object with the following options:
\r
2544 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
\r
2545 * @param {Function} fn The function to call
\r
2546 * @param {Object} scope (optional) The scope of the function
\r
2547 * @return {Ext.KeyMap} The KeyMap created
\r
2549 addKeyListener : function(key, fn, scope){
\r
2551 if(typeof key != "object" || Ext.isArray(key)){
\r
2560 shift : key.shift,
\r
2567 return new Ext.KeyMap(this, config);
\r
2571 * Creates a KeyMap for this element
\r
2572 * @param {Object} config The KeyMap config. See {@link Ext.KeyMap} for more details
\r
2573 * @return {Ext.KeyMap} The KeyMap created
\r
2575 addKeyMap : function(config){
\r
2576 return new Ext.KeyMap(this, config);
\r
2580 * Returns true if this element is scrollable.
\r
2581 * @return {Boolean}
\r
2583 isScrollable : function(){
\r
2584 var dom = this.dom;
\r
2585 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
\r
2589 * Scrolls this element the specified scroll point. It does NOT do bounds checking so if you scroll to a weird value it will try to do it. For auto bounds checking, use scroll().
\r
2590 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
\r
2591 * @param {Number} value The new scroll value
\r
2592 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
2593 * @return {Element} this
\r
2595 scrollTo : function(side, value, animate){
\r
2596 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
\r
2597 if(!animate || !A){
\r
2598 this.dom[prop] = value;
\r
2600 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
\r
2601 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
\r
2607 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
\r
2608 * within this element's scrollable range.
\r
2609 * @param {String} direction Possible values are: "l" (or "left"), "r" (or "right"), "t" (or "top", or "up"), "b" (or "bottom", or "down").
\r
2610 * @param {Number} distance How far to scroll the element in pixels
\r
2611 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
\r
2612 * @return {Boolean} Returns true if a scroll was triggered or false if the element
\r
2613 * was scrolled as far as it could go.
\r
2615 scroll : function(direction, distance, animate){
\r
2616 if(!this.isScrollable()){
\r
2619 var el = this.dom;
\r
2620 var l = el.scrollLeft, t = el.scrollTop;
\r
2621 var w = el.scrollWidth, h = el.scrollHeight;
\r
2622 var cw = el.clientWidth, ch = el.clientHeight;
\r
2623 direction = direction.toLowerCase();
\r
2624 var scrolled = false;
\r
2625 var a = this.preanim(arguments, 2);
\r
2626 switch(direction){
\r
2630 var v = Math.min(l + distance, w-cw);
\r
2631 this.scrollTo("left", v, a);
\r
2638 var v = Math.max(l - distance, 0);
\r
2639 this.scrollTo("left", v, a);
\r
2647 var v = Math.max(t - distance, 0);
\r
2648 this.scrollTo("top", v, a);
\r
2656 var v = Math.min(t + distance, h-ch);
\r
2657 this.scrollTo("top", v, a);
\r
2666 * Translates the passed page coordinates into left/top css values for this element
\r
2667 * @param {Number/Array} x The page x or an array containing [x, y]
\r
2668 * @param {Number} y (optional) The page y, required if x is not an array
\r
2669 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
\r
2671 translatePoints : function(x, y){
\r
2672 if(typeof x == 'object' || Ext.isArray(x)){
\r
2673 y = x[1]; x = x[0];
\r
2675 var p = this.getStyle('position');
\r
2676 var o = this.getXY();
\r
2678 var l = parseInt(this.getStyle('left'), 10);
\r
2679 var t = parseInt(this.getStyle('top'), 10);
\r
2682 l = (p == "relative") ? 0 : this.dom.offsetLeft;
\r
2685 t = (p == "relative") ? 0 : this.dom.offsetTop;
\r
2688 return {left: (x - o[0] + l), top: (y - o[1] + t)};
\r
2692 * Returns the current scroll position of the element.
\r
2693 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
\r
2695 getScroll : function(){
\r
2696 var d = this.dom, doc = document;
\r
2697 if(d == doc || d == doc.body){
\r
2699 if(Ext.isIE && Ext.isStrict){
\r
2700 l = doc.documentElement.scrollLeft || (doc.body.scrollLeft || 0);
\r
2701 t = doc.documentElement.scrollTop || (doc.body.scrollTop || 0);
\r
2703 l = window.pageXOffset || (doc.body.scrollLeft || 0);
\r
2704 t = window.pageYOffset || (doc.body.scrollTop || 0);
\r
2706 return {left: l, top: t};
\r
2708 return {left: d.scrollLeft, top: d.scrollTop};
\r
2713 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
\r
2714 * are convert to standard 6 digit hex color.
\r
2715 * @param {String} attr The css attribute
\r
2716 * @param {String} defaultValue The default value to use when a valid color isn't found
\r
2717 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
\r
2720 getColor : function(attr, defaultValue, prefix){
\r
2721 var v = this.getStyle(attr);
\r
2722 if(!v || v == "transparent" || v == "inherit") {
\r
2723 return defaultValue;
\r
2725 var color = typeof prefix == "undefined" ? "#" : prefix;
\r
2726 if(v.substr(0, 4) == "rgb("){
\r
2727 var rvs = v.slice(4, v.length -1).split(",");
\r
2728 for(var i = 0; i < 3; i++){
\r
2729 var h = parseInt(rvs[i]);
\r
2730 var s = h.toString(16);
\r
2737 if(v.substr(0, 1) == "#"){
\r
2738 if(v.length == 4) {
\r
2739 for(var i = 1; i < 4; i++){
\r
2740 var c = v.charAt(i);
\r
2743 }else if(v.length == 7){
\r
2744 color += v.substr(1);
\r
2748 return(color.length > 5 ? color.toLowerCase() : defaultValue);
\r
2752 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
\r
2753 * gradient background, rounded corners and a 4-way shadow. Example usage:
\r
2756 Ext.get("foo").boxWrap();
\r
2758 // You can also add a custom class and use CSS inheritance rules to customize the box look.
\r
2759 // 'x-box-blue' is a built-in alternative -- look at the related CSS definitions as an example
\r
2760 // for how to create a custom box wrap style.
\r
2761 Ext.get("foo").boxWrap().addClass("x-box-blue");
\r
2763 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
\r
2764 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
\r
2765 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
\r
2766 * @return {Ext.Element} this
\r
2768 boxWrap : function(cls){
\r
2769 cls = cls || 'x-box';
\r
2770 var el = Ext.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
\r
2771 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
\r
2776 * Returns the value of a namespaced attribute from the element's underlying DOM node.
\r
2777 * @param {String} namespace The namespace in which to look for the attribute
\r
2778 * @param {String} name The attribute name
\r
2779 * @return {String} The attribute value
\r
2781 getAttributeNS : Ext.isIE ? function(ns, name){
\r
2783 var type = typeof d[ns+":"+name];
\r
2784 if(type != 'undefined' && type != 'unknown'){
\r
2785 return d[ns+":"+name];
\r
2788 } : function(ns, name){
\r
2790 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
\r
2794 * Returns the width in pixels of the passed text, or the width of the text in this Element.
\r
2795 * @param {String} text The text to measure. Defaults to the innerHTML of the element.
\r
2796 * @param {Number} min (Optional) The minumum value to return.
\r
2797 * @param {Number} max (Optional) The maximum value to return.
\r
2798 * @return {Number} The text width in pixels.
\r
2800 getTextWidth : function(text, min, max){
\r
2801 return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
\r
2805 var ep = El.prototype;
\r
2808 * Appends an event handler (shorthand for {@link #addListener}).
\r
2809 * @param {String} eventName The type of event to handle
\r
2810 * @param {Function} fn The handler function the event invokes
\r
2811 * @param {Object} scope (optional) The scope (this element) of the handler function
\r
2812 * @param {Object} options (optional) An object containing standard {@link #addListener} options
\r
2813 * @member Ext.Element
\r
2816 ep.on = ep.addListener;
\r
2817 // backwards compat
\r
2818 ep.mon = ep.addListener;
\r
2820 ep.getUpdateManager = ep.getUpdater;
\r
2823 * Removes an event handler from this element (shorthand for {@link #removeListener}).
\r
2824 * @param {String} eventName the type of event to remove
\r
2825 * @param {Function} fn the method the event invokes
\r
2826 * @param {Object} scope (optional) The scope (The <tt>this</tt> reference) of the handler function. Defaults
\r
2827 * to this Element.
\r
2828 * @return {Ext.Element} this
\r
2829 * @member Ext.Element
\r
2832 ep.un = ep.removeListener;
\r
2835 * true to automatically adjust width and height settings for box-model issues (default to true)
\r
2837 ep.autoBoxAdjust = true;
\r
2840 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
\r
2843 El.addUnits = function(v, defaultUnit){
\r
2844 if(v === "" || v == "auto"){
\r
2847 if(v === undefined){
\r
2850 if(typeof v == "number" || !El.unitPattern.test(v)){
\r
2851 return v + (defaultUnit || 'px');
\r
2856 // special markup used throughout Ext when box wrapping elements
\r
2857 El.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
\r
2859 * Visibility mode constant - Use visibility to hide element
\r
2863 El.VISIBILITY = 1;
\r
2865 * Visibility mode constant - Use display to hide element
\r
2871 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
\r
2872 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
\r
2873 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
\r
2885 * Static method to retrieve Ext.Element objects.
\r
2886 * <p><b>This method does not retrieve {@link Ext.Component Component}s.</b> This method
\r
2887 * retrieves Ext.Element objects which encapsulate DOM elements. To retrieve a Component by
\r
2888 * its ID, use {@link Ext.ComponentMgr#get}.</p>
\r
2889 * <p>Uses simple caching to consistently return the same object.
\r
2890 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.</p>
\r
2891 * @param {Mixed} el The id of the node, a DOM Node or an existing Element.
\r
2892 * @return {Element} The {@link Ext.Element Element} object (or null if no matching element was found)
\r
2895 El.get = function(el){
\r
2897 if(!el){ return null; }
\r
2898 if(typeof el == "string"){ // element id
\r
2899 if(!(elm = document.getElementById(el))){
\r
2902 if(ex = El.cache[el]){
\r
2905 ex = El.cache[el] = new El(elm);
\r
2908 }else if(el.tagName){ // dom element
\r
2909 if(!(id = el.id)){
\r
2912 if(ex = El.cache[id]){
\r
2915 ex = El.cache[id] = new El(el);
\r
2918 }else if(el instanceof El){
\r
2920 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
\r
2921 // catch case where it hasn't been appended
\r
2922 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
\r
2925 }else if(el.isComposite){
\r
2927 }else if(Ext.isArray(el)){
\r
2928 return El.select(el);
\r
2929 }else if(el == document){
\r
2930 // create a bogus element object representing the document object
\r
2932 var f = function(){};
\r
2933 f.prototype = El.prototype;
\r
2935 docEl.dom = document;
\r
2943 El.uncache = function(el){
\r
2944 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
\r
2946 delete El.cache[a[i].id || a[i]];
\r
2952 // Garbage collection - uncache elements/purge listeners on orphaned elements
\r
2953 // so we don't hold a reference and cause the browser to retain them
\r
2954 El.garbageCollect = function(){
\r
2955 if(!Ext.enableGarbageCollector){
\r
2956 clearInterval(El.collectorThread);
\r
2959 for(var eid in El.cache){
\r
2960 var el = El.cache[eid], d = el.dom;
\r
2961 // -------------------------------------------------------
\r
2962 // Determining what is garbage:
\r
2963 // -------------------------------------------------------
\r
2965 // dom node is null, definitely garbage
\r
2966 // -------------------------------------------------------
\r
2968 // no parentNode == direct orphan, definitely garbage
\r
2969 // -------------------------------------------------------
\r
2970 // !d.offsetParent && !document.getElementById(eid)
\r
2971 // display none elements have no offsetParent so we will
\r
2972 // also try to look it up by it's id. However, check
\r
2973 // offsetParent first so we don't do unneeded lookups.
\r
2974 // This enables collection of elements that are not orphans
\r
2975 // directly, but somewhere up the line they have an orphan
\r
2977 // -------------------------------------------------------
\r
2978 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
\r
2979 delete El.cache[eid];
\r
2980 if(d && Ext.enableListenerCollection){
\r
2981 Ext.EventManager.removeAll(d);
\r
2986 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
\r
2988 var flyFn = function(){};
\r
2989 flyFn.prototype = El.prototype;
\r
2990 var _cls = new flyFn();
\r
2992 // dom is optional
\r
2993 El.Flyweight = function(dom){
\r
2997 El.Flyweight.prototype = _cls;
\r
2998 El.Flyweight.prototype.isFlyweight = true;
\r
3000 El._flyweights = {};
\r
3002 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
\r
3003 * the dom node can be overwritten by other code.
\r
3004 * @param {String/HTMLElement} el The dom node or id
\r
3005 * @param {String} named (optional) Allows for creation of named reusable flyweights to
\r
3006 * prevent conflicts (e.g. internally Ext uses "_internal")
\r
3008 * @return {Element} The shared Element object (or null if no matching element was found)
\r
3010 El.fly = function(el, named){
\r
3011 named = named || '_global';
\r
3012 el = Ext.getDom(el);
\r
3016 if(!El._flyweights[named]){
\r
3017 El._flyweights[named] = new El.Flyweight();
\r
3019 El._flyweights[named].dom = el;
\r
3020 return El._flyweights[named];
\r
3024 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
\r
3025 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
\r
3026 * Shorthand of {@link Ext.Element#get}
\r
3027 * @param {Mixed} el The id of the node, a DOM Node or an existing Element.
\r
3028 * @return {Element} The Element object
\r
3034 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
\r
3035 * the dom node can be overwritten by other code.
\r
3036 * Shorthand of {@link Ext.Element#fly}
\r
3037 * @param {String/HTMLElement} el The dom node or id
\r
3038 * @param {String} named (optional) Allows for creation of named reusable flyweights to
\r
3039 * prevent conflicts (e.g. internally Ext uses "_internal")
\r
3041 * @return {Element} The shared Element object
\r
3047 // speedy lookup for elements never to box adjust
\r
3048 var noBoxAdjust = Ext.isStrict ? {
\r
3051 input:1, select:1, textarea:1
\r
3053 if(Ext.isIE || Ext.isGecko){
\r
3054 noBoxAdjust['button'] = 1;
\r
3058 Ext.EventManager.on(window, 'unload', function(){
\r
3060 delete El._flyweights;
\r