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