Upgrade to ExtJS 3.2.2 - Released 06/02/2010
[extjs.git] / src / core / Element-more.js
1 /*!
2  * Ext JS Library 3.2.2
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.Element
9  */
10 Ext.Element.addMethods({
11     /**
12      * Stops the specified event(s) from bubbling and optionally prevents the default action
13      * @param {String/Array} eventName an event / array of events to stop from bubbling
14      * @param {Boolean} preventDefault (optional) true to prevent the default action too
15      * @return {Ext.Element} this
16      */
17     swallowEvent : function(eventName, preventDefault){
18         var me = this;
19         function fn(e){
20             e.stopPropagation();
21             if(preventDefault){
22                 e.preventDefault();
23             }
24         }
25         if(Ext.isArray(eventName)){
26             Ext.each(eventName, function(e) {
27                  me.on(e, fn);
28             });
29             return me;
30         }
31         me.on(eventName, fn);
32         return me;
33     },
34
35     /**
36      * Create an event handler on this element such that when the event fires and is handled by this element,
37      * it will be relayed to another object (i.e., fired again as if it originated from that object instead).
38      * @param {String} eventName The type of event to relay
39      * @param {Object} object Any object that extends {@link Ext.util.Observable} that will provide the context
40      * for firing the relayed event
41      */
42     relayEvent : function(eventName, observable){
43         this.on(eventName, function(e){
44             observable.fireEvent(eventName, e);
45         });
46     },
47
48     /**
49      * Removes worthless text nodes
50      * @param {Boolean} forceReclean (optional) By default the element
51      * keeps track if it has been cleaned already so
52      * you can call this over and over. However, if you update the element and
53      * need to force a reclean, you can pass true.
54      */
55     clean : function(forceReclean){
56         var me = this,
57             dom = me.dom,
58             n = dom.firstChild,
59             ni = -1;
60
61         if(Ext.Element.data(dom, 'isCleaned') && forceReclean !== true){
62             return me;
63         }
64
65         while(n){
66             var nx = n.nextSibling;
67             if(n.nodeType == 3 && !/\S/.test(n.nodeValue)){
68                 dom.removeChild(n);
69             }else{
70                 n.nodeIndex = ++ni;
71             }
72             n = nx;
73         }
74         Ext.Element.data(dom, 'isCleaned', true);
75         return me;
76     },
77
78     /**
79      * Direct access to the Updater {@link Ext.Updater#update} method. The method takes the same object
80      * parameter as {@link Ext.Updater#update}
81      * @return {Ext.Element} this
82      */
83     load : function(){
84         var um = this.getUpdater();
85         um.update.apply(um, arguments);
86         return this;
87     },
88
89     /**
90     * Gets this element's {@link Ext.Updater Updater}
91     * @return {Ext.Updater} The Updater
92     */
93     getUpdater : function(){
94         return this.updateManager || (this.updateManager = new Ext.Updater(this));
95     },
96
97     /**
98     * Update the innerHTML of this element, optionally searching for and processing scripts
99     * @param {String} html The new HTML
100     * @param {Boolean} loadScripts (optional) True to look for and process scripts (defaults to false)
101     * @param {Function} callback (optional) For async script loading you can be notified when the update completes
102     * @return {Ext.Element} this
103      */
104     update : function(html, loadScripts, callback){
105         if (!this.dom) {
106             return this;
107         }
108         html = html || "";
109
110         if(loadScripts !== true){
111             this.dom.innerHTML = html;
112             if(typeof callback == 'function'){
113                 callback();
114             }
115             return this;
116         }
117
118         var id = Ext.id(),
119             dom = this.dom;
120
121         html += '<span id="' + id + '"></span>';
122
123         Ext.lib.Event.onAvailable(id, function(){
124             var DOC = document,
125                 hd = DOC.getElementsByTagName("head")[0],
126                 re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
127                 srcRe = /\ssrc=([\'\"])(.*?)\1/i,
128                 typeRe = /\stype=([\'\"])(.*?)\1/i,
129                 match,
130                 attrs,
131                 srcMatch,
132                 typeMatch,
133                 el,
134                 s;
135
136             while((match = re.exec(html))){
137                 attrs = match[1];
138                 srcMatch = attrs ? attrs.match(srcRe) : false;
139                 if(srcMatch && srcMatch[2]){
140                    s = DOC.createElement("script");
141                    s.src = srcMatch[2];
142                    typeMatch = attrs.match(typeRe);
143                    if(typeMatch && typeMatch[2]){
144                        s.type = typeMatch[2];
145                    }
146                    hd.appendChild(s);
147                 }else if(match[2] && match[2].length > 0){
148                     if(window.execScript) {
149                        window.execScript(match[2]);
150                     } else {
151                        window.eval(match[2]);
152                     }
153                 }
154             }
155             el = DOC.getElementById(id);
156             if(el){Ext.removeNode(el);}
157             if(typeof callback == 'function'){
158                 callback();
159             }
160         });
161         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
162         return this;
163     },
164
165     // inherit docs, overridden so we can add removeAnchor
166     removeAllListeners : function(){
167         this.removeAnchor();
168         Ext.EventManager.removeAll(this.dom);
169         return this;
170     },
171
172     /**
173      * Creates a proxy element of this element
174      * @param {String/Object} config The class name of the proxy element or a DomHelper config object
175      * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
176      * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
177      * @return {Ext.Element} The new proxy element
178      */
179     createProxy : function(config, renderTo, matchBox){
180         config = (typeof config == 'object') ? config : {tag : "div", cls: config};
181
182         var me = this,
183             proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
184                                Ext.DomHelper.insertBefore(me.dom, config, true);
185
186         if(matchBox && me.setBox && me.getBox){ // check to make sure Element.position.js is loaded
187            proxy.setBox(me.getBox());
188         }
189         return proxy;
190     }
191 });
192
193 Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;