Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / direct / Manager.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.direct.Manager
17  * <p><b><u>Overview</u></b></p>
18  *
19  * <p>Ext.Direct aims to streamline communication between the client and server
20  * by providing a single interface that reduces the amount of common code
21  * typically required to validate data and handle returned data packets
22  * (reading data, error conditions, etc).</p>
23  *
24  * <p>The Ext.direct namespace includes several classes for a closer integration
25  * with the server-side. The Ext.data namespace also includes classes for working
26  * with Ext.data.Stores which are backed by data from an Ext.Direct method.</p>
27  *
28  * <p><b><u>Specification</u></b></p>
29  *
30  * <p>For additional information consult the
31  * <a href="http://sencha.com/products/extjs/extdirect">Ext.Direct Specification</a>.</p>
32  *
33  * <p><b><u>Providers</u></b></p>
34  *
35  * <p>Ext.Direct uses a provider architecture, where one or more providers are
36  * used to transport data to and from the server. There are several providers
37  * that exist in the core at the moment:</p><div class="mdetail-params"><ul>
38  *
39  * <li>{@link Ext.direct.JsonProvider JsonProvider} for simple JSON operations</li>
40  * <li>{@link Ext.direct.PollingProvider PollingProvider} for repeated requests</li>
41  * <li>{@link Ext.direct.RemotingProvider RemotingProvider} exposes server side
42  * on the client.</li>
43  * </ul></div>
44  *
45  * <p>A provider does not need to be invoked directly, providers are added via
46  * {@link Ext.direct.Manager}.{@link Ext.direct.Manager#addProvider addProvider}.</p>
47  *
48  * <p><b><u>Router</u></b></p>
49  *
50  * <p>Ext.Direct utilizes a "router" on the server to direct requests from the client
51  * to the appropriate server-side method. Because the Ext.Direct API is completely
52  * platform-agnostic, you could completely swap out a Java based server solution
53  * and replace it with one that uses C# without changing the client side JavaScript
54  * at all.</p>
55  *
56  * <p><b><u>Server side events</u></b></p>
57  *
58  * <p>Custom events from the server may be handled by the client by adding
59  * listeners, for example:</p>
60  * <pre><code>
61 {"type":"event","name":"message","data":"Successfully polled at: 11:19:30 am"}
62
63 // add a handler for a 'message' event sent by the server
64 Ext.direct.Manager.on('message', function(e){
65     out.append(String.format('&lt;p>&lt;i>{0}&lt;/i>&lt;/p>', e.data));
66             out.el.scrollTo('t', 100000, true);
67 });
68  * </code></pre>
69  * @singleton
70  */
71
72 Ext.define('Ext.direct.Manager', {
73     
74     /* Begin Definitions */
75     singleton: true,
76    
77     mixins: {
78         observable: 'Ext.util.Observable'
79     },
80     
81     requires: ['Ext.util.MixedCollection'],
82     
83     statics: {
84         exceptions: {
85             TRANSPORT: 'xhr',
86             PARSE: 'parse',
87             LOGIN: 'login',
88             SERVER: 'exception'
89         }
90     },
91     
92     /* End Definitions */
93    
94     constructor: function(){
95         var me = this;
96        
97         me.addEvents(
98             /**
99              * @event event
100              * Fires after an event.
101              * @param {event} e The Ext.direct.Event type that occurred.
102              * @param {Ext.direct.Provider} provider The {@link Ext.direct.Provider Provider}.
103              */
104             'event',
105             /**
106              * @event exception
107              * Fires after an event exception.
108              * @param {event} e The Ext.direct.Event type that occurred.
109              */
110             'exception'
111         );
112         me.transactions = Ext.create('Ext.util.MixedCollection');
113         me.providers = Ext.create('Ext.util.MixedCollection');
114         
115         me.mixins.observable.constructor.call(me);
116     },
117     
118     /**
119      * Adds an Ext.Direct Provider and creates the proxy or stub methods to execute server-side methods.
120      * If the provider is not already connected, it will auto-connect.
121      * <pre><code>
122 var pollProv = new Ext.direct.PollingProvider({
123     url: 'php/poll2.php'
124 });
125
126 Ext.direct.Manager.addProvider({
127     "type":"remoting",       // create a {@link Ext.direct.RemotingProvider}
128     "url":"php\/router.php", // url to connect to the Ext.Direct server-side router.
129     "actions":{              // each property within the actions object represents a Class
130         "TestAction":[       // array of methods within each server side Class
131         {
132             "name":"doEcho", // name of method
133             "len":1
134         },{
135             "name":"multiply",
136             "len":1
137         },{
138             "name":"doForm",
139             "formHandler":true, // handle form on server with Ext.Direct.Transaction
140             "len":1
141         }]
142     },
143     "namespace":"myApplication",// namespace to create the Remoting Provider in
144 },{
145     type: 'polling', // create a {@link Ext.direct.PollingProvider}
146     url:  'php/poll.php'
147 }, pollProv); // reference to previously created instance
148      * </code></pre>
149      * @param {Object/Array} provider Accepts either an Array of Provider descriptions (an instance
150      * or config object for a Provider) or any number of Provider descriptions as arguments.  Each
151      * Provider description instructs Ext.Direct how to create client-side stub methods.
152      */
153     addProvider : function(provider){
154         var me = this,
155             args = arguments,
156             i = 0,
157             len;
158             
159         if (args.length > 1) {
160             for (len = args.length; i < len; ++i) {
161                 me.addProvider(args[i]);
162             }
163             return;
164         }
165
166         // if provider has not already been instantiated
167         if (!provider.isProvider) {
168             provider = Ext.create('direct.' + provider.type + 'provider', provider);
169         }
170         me.providers.add(provider);
171         provider.on('data', me.onProviderData, me);
172
173
174         if (!provider.isConnected()) {
175             provider.connect();
176         }
177
178         return provider;
179     },
180     
181     /**
182      * Retrieve a {@link Ext.direct.Provider provider} by the
183      * <b><tt>{@link Ext.direct.Provider#id id}</tt></b> specified when the provider is
184      * {@link #addProvider added}.
185      * @param {String/Ext.data.Provider} id The id of the provider, or the provider instance.
186      */
187     getProvider : function(id){
188         return id.isProvider ? id : this.providers.get(id);
189     },
190     
191     /**
192      * Removes the provider.
193      * @param {String/Ext.direct.Provider} provider The provider instance or the id of the provider.
194      * @return {Ext.direct.Provider} The provider, null if not found.
195      */
196     removeProvider : function(provider){
197         var me = this,
198             providers = me.providers,
199             provider = provider.isProvider ? provider : providers.get(provider);
200             
201         if (provider) {
202             provider.un('data', me.onProviderData, me);
203             providers.remove(provider);
204             return provider;
205         }
206         return null;
207     },
208     
209     /**
210      * Add a transaction to the manager.
211      * @private
212      * @param {Ext.direct.Transaction} transaction The transaction to add
213      * @return {Ext.direct.Transaction} transaction
214      */
215     addTransaction: function(transaction){
216         this.transactions.add(transaction);
217         return transaction;
218     },
219
220     /**
221      * Remove a transaction from the manager.
222      * @private
223      * @param {String/Ext.direct.Transaction} transaction The transaction/id of transaction to remove
224      * @return {Ext.direct.Transaction} transaction
225      */
226     removeTransaction: function(transaction){
227         transaction = this.getTransaction(transaction);
228         this.transactions.remove(transaction);
229         return transaction;
230     },
231
232     /**
233      * Gets a transaction
234      * @private
235      * @param {String/Ext.direct.Transaction} transaction The transaction/id of transaction to get
236      * @return {Ext.direct.Transaction}
237      */
238     getTransaction: function(transaction){
239         return transaction.isTransaction ? transaction : this.transactions.get(transaction);
240     },
241     
242     onProviderData : function(provider, event){
243         var me = this,
244             i = 0,
245             len;
246             
247         if (Ext.isArray(event)) {
248             for (len = event.length; i < len; ++i) {
249                 me.onProviderData(provider, event[i]);
250             }
251             return;
252         }
253         if (event.name && event.name != 'event' && event.name != 'exception') {
254             me.fireEvent(event.name, event);
255         } else if (event.type == 'exception') {
256             me.fireEvent('exception', event);
257         }
258         me.fireEvent('event', event, provider);
259     }
260 }, function(){
261     // Backwards compatibility
262     Ext.Direct = Ext.direct.Manager;
263 });
264