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