Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / docs / source / Observable-more.html
1 <html>
2 <head>
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
4   <title>The source code</title>
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
7 </head>
8 <body  onload="prettyPrint();">
9     <pre class="prettyprint lang-js">/*!
10  * Ext JS Library 3.2.0
11  * Copyright(c) 2006-2010 Ext JS, Inc.
12  * licensing@extjs.com
13  * http://www.extjs.com/license
14  */
15 /**
16  * @class Ext.util.Observable
17  */
18 Ext.apply(Ext.util.Observable.prototype, function(){
19     // this is considered experimental (along with beforeMethod, afterMethod, removeMethodListener?)
20     // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
21     // private
22     function getMethodEvent(method){
23         var e = (this.methodEvents = this.methodEvents ||
24         {})[method], returnValue, v, cancel, obj = this;
25
26         if (!e) {
27             this.methodEvents[method] = e = {};
28             e.originalFn = this[method];
29             e.methodName = method;
30             e.before = [];
31             e.after = [];
32
33             var makeCall = function(fn, scope, args){
34                 if (!Ext.isEmpty(v = fn.apply(scope || obj, args))) {
35                     if (Ext.isObject(v)) {
36                         returnValue = !Ext.isEmpty(v.returnValue) ? v.returnValue : v;
37                         cancel = !!v.cancel;
38                     }
39                     else
40                         if (v === false) {
41                             cancel = true;
42                         }
43                         else {
44                             returnValue = v;
45                         }
46                 }
47             };
48
49             this[method] = function(){
50                 var args = Ext.toArray(arguments);
51                 returnValue = v = undefined;
52                 cancel = false;
53
54                 Ext.each(e.before, function(b){
55                     makeCall(b.fn, b.scope, args);
56                     if (cancel) {
57                         return returnValue;
58                     }
59                 });
60
61                 if (!Ext.isEmpty(v = e.originalFn.apply(obj, args))) {
62                     returnValue = v;
63                 }
64                 Ext.each(e.after, function(a){
65                     makeCall(a.fn, a.scope, args);
66                     if (cancel) {
67                         return returnValue;
68                     }
69                 });
70                 return returnValue;
71             };
72         }
73         return e;
74     }
75
76     return {
77         // these are considered experimental
78         // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
79         // adds an 'interceptor' called before the original method
80         beforeMethod : function(method, fn, scope){
81             getMethodEvent.call(this, method).before.push({
82                 fn: fn,
83                 scope: scope
84             });
85         },
86
87         // adds a 'sequence' called after the original method
88         afterMethod : function(method, fn, scope){
89             getMethodEvent.call(this, method).after.push({
90                 fn: fn,
91                 scope: scope
92             });
93         },
94
95         removeMethodListener: function(method, fn, scope){
96             var e = getMethodEvent.call(this, method), found = false;
97             Ext.each(e.before, function(b, i, arr){
98                 if (b.fn == fn && b.scope == scope) {
99                     arr.splice(i, 1);
100                     found = true;
101                     return false;
102                 }
103             });
104             if (!found) {
105                 Ext.each(e.after, function(a, i, arr){
106                     if (a.fn == fn && a.scope == scope) {
107                         arr.splice(i, 1);
108                         return false;
109                     }
110                 });
111             }
112         },
113
114         <div id="method-Ext.util.Observable-relayEvents"></div>/**
115          * Relays selected events from the specified Observable as if the events were fired by <tt><b>this</b></tt>.
116          * @param {Object} o The Observable whose events this object is to relay.
117          * @param {Array} events Array of event names to relay.
118          */
119         relayEvents : function(o, events){
120             var me = this;
121             function createHandler(ename){
122                 return function(){
123                     return me.fireEvent.apply(me, [ename].concat(Ext.toArray(arguments)));
124                 };
125             }
126             Ext.each(events, function(ename){
127                 me.events[ename] = me.events[ename] || true;
128                 o.on(ename, createHandler(ename), me);
129             });
130         },
131
132         <div id="method-Ext.util.Observable-enableBubble"></div>/**
133          * <p>Enables events fired by this Observable to bubble up an owner hierarchy by calling
134          * <code>this.getBubbleTarget()</code> if present. There is no implementation in the Observable base class.</p>
135          * <p>This is commonly used by Ext.Components to bubble events to owner Containers. See {@link Ext.Component.getBubbleTarget}. The default
136          * implementation in Ext.Component returns the Component's immediate owner. But if a known target is required, this can be overridden to
137          * access the required target more quickly.</p>
138          * <p>Example:</p><pre><code>
139 Ext.override(Ext.form.Field, {
140     //  Add functionality to Field&#39;s initComponent to enable the change event to bubble
141     initComponent : Ext.form.Field.prototype.initComponent.createSequence(function() {
142         this.enableBubble('change');
143     }),
144
145     //  We know that we want Field&#39;s events to bubble directly to the FormPanel.
146     getBubbleTarget : function() {
147         if (!this.formPanel) {
148             this.formPanel = this.findParentByType('form');
149         }
150         return this.formPanel;
151     }
152 });
153
154 var myForm = new Ext.formPanel({
155     title: 'User Details',
156     items: [{
157         ...
158     }],
159     listeners: {
160         change: function() {
161             // Title goes red if form has been modified.
162             myForm.header.setStyle('color', 'red');
163         }
164     }
165 });
166 </code></pre>
167          * @param {String/Array} events The event name to bubble, or an Array of event names.
168          */
169         enableBubble : function(events){
170             var me = this;
171             if(!Ext.isEmpty(events)){
172                 events = Ext.isArray(events) ? events : Ext.toArray(arguments);
173                 Ext.each(events, function(ename){
174                     ename = ename.toLowerCase();
175                     var ce = me.events[ename] || true;
176                     if (Ext.isBoolean(ce)) {
177                         ce = new Ext.util.Event(me, ename);
178                         me.events[ename] = ce;
179                     }
180                     ce.bubble = true;
181                 });
182             }
183         }
184     };
185 }());
186
187
188 <div id="method-Ext.util.Observable-Observable.capture"></div>/**
189  * Starts capture on the specified Observable. All events will be passed
190  * to the supplied function with the event name + standard signature of the event
191  * <b>before</b> the event is fired. If the supplied function returns false,
192  * the event will not fire.
193  * @param {Observable} o The Observable to capture events from.
194  * @param {Function} fn The function to call when an event is fired.
195  * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the Observable firing the event.
196  * @static
197  */
198 Ext.util.Observable.capture = function(o, fn, scope){
199     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
200 };
201
202
203 <div id="method-Ext.util.Observable-Observable.observeClass"></div>/**
204  * Sets observability on the passed class constructor.<p>
205  * <p>This makes any event fired on any instance of the passed class also fire a single event through
206  * the <i>class</i> allowing for central handling of events on many instances at once.</p>
207  * <p>Usage:</p><pre><code>
208 Ext.util.Observable.observeClass(Ext.data.Connection);
209 Ext.data.Connection.on('beforerequest', function(con, options) {
210     console.log('Ajax request made to ' + options.url);
211 });</code></pre>
212  * @param {Function} c The class constructor to make observable.
213  * @param {Object} listeners An object containing a series of listeners to add. See {@link #addListener}. 
214  * @static
215  */
216 Ext.util.Observable.observeClass = function(c, listeners){
217     if(c){
218       if(!c.fireEvent){
219           Ext.apply(c, new Ext.util.Observable());
220           Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
221       }
222       if(Ext.isObject(listeners)){
223           c.on(listeners);
224       }
225       return c;
226    }
227 };</pre>    
228 </body>
229 </html>