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