]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | /**\r |
2 | * This singleton manages simulated Ajax responses. This allows application logic to be\r | |
3 | * written unaware that its Ajax calls are being handled by simulations ("simlets"). This\r | |
4 | * is currently done by hooking {@link Ext.data.Connection} methods, so all users of that\r | |
5 | * class (and {@link Ext.Ajax} since it is a derived class) qualify for simulation.\r | |
6 | *\r | |
7 | * The requires hooks are inserted when either the {@link #init} method is called or the\r | |
8 | * first {@link Ext.ux.ajax.Simlet} is registered. For example:\r | |
9 | *\r | |
10 | * Ext.onReady(function () {\r | |
11 | * initAjaxSim();\r | |
12 | *\r | |
13 | * // normal stuff\r | |
14 | * });\r | |
15 | *\r | |
16 | * function initAjaxSim () {\r | |
17 | * Ext.ux.ajax.SimManager.init({\r | |
18 | * delay: 300\r | |
19 | * }).register({\r | |
20 | * '/app/data/url': {\r | |
21 | * type: 'json', // use JsonSimlet (type is like xtype for components)\r | |
22 | * data: [\r | |
23 | * { foo: 42, bar: 'abc' },\r | |
24 | * ...\r | |
25 | * ]\r | |
26 | * }\r | |
27 | * });\r | |
28 | * }\r | |
29 | *\r | |
30 | * As many URL's as desired can be registered and associated with a {@link Ext.ux.ajax.Simlet}. To make\r | |
31 | * non-simulated Ajax requests once this singleton is initialized, add a `nosim:true` option\r | |
32 | * to the Ajax options:\r | |
33 | *\r | |
34 | * Ext.Ajax.request({\r | |
35 | * url: 'page.php',\r | |
36 | * nosim: true, // ignored by normal Ajax request\r | |
37 | * params: {\r | |
38 | * id: 1\r | |
39 | * },\r | |
40 | * success: function(response){\r | |
41 | * var text = response.responseText;\r | |
42 | * // process server response here\r | |
43 | * }\r | |
44 | * });\r | |
45 | */\r | |
46 | Ext.define('Ext.ux.ajax.SimManager', {\r | |
47 | singleton: true,\r | |
48 | \r | |
49 | requires: [\r | |
50 | 'Ext.data.Connection',\r | |
51 | 'Ext.ux.ajax.SimXhr',\r | |
52 | 'Ext.ux.ajax.Simlet',\r | |
53 | 'Ext.ux.ajax.JsonSimlet'\r | |
54 | ],\r | |
55 | \r | |
56 | /**\r | |
57 | * @cfg {Ext.ux.ajax.Simlet} defaultSimlet\r | |
58 | * The {@link Ext.ux.ajax.Simlet} instance to use for non-matching URL's. By default, this will\r | |
59 | * return 404. Set this to null to use real Ajax calls for non-matching URL's.\r | |
60 | */\r | |
61 | \r | |
62 | /**\r | |
63 | * @cfg {String} defaultType\r | |
64 | * The default `type` to apply to generic {@link Ext.ux.ajax.Simlet} configuration objects. The\r | |
65 | * default is 'basic'.\r | |
66 | */\r | |
67 | defaultType: 'basic',\r | |
68 | \r | |
69 | /**\r | |
70 | * @cfg {Number} delay\r | |
71 | * The number of milliseconds to delay before delivering a response to an async request.\r | |
72 | */\r | |
73 | delay: 150,\r | |
74 | \r | |
75 | /**\r | |
76 | * @property {Boolean} ready\r | |
77 | * True once this singleton has initialized and applied its Ajax hooks.\r | |
78 | * @private\r | |
79 | */\r | |
80 | ready: false,\r | |
81 | \r | |
82 | constructor: function () {\r | |
83 | this.simlets = [];\r | |
84 | },\r | |
85 | \r | |
86 | getSimlet: function (url) {\r | |
87 | // Strip down to base URL (no query parameters or hash):\r | |
88 | var me = this,\r | |
89 | index = url.indexOf('?'),\r | |
90 | simlets = me.simlets,\r | |
91 | len = simlets.length,\r | |
92 | i, simlet, simUrl, match;\r | |
93 | \r | |
94 | if (index < 0) {\r | |
95 | index = url.indexOf('#');\r | |
96 | }\r | |
97 | if (index > 0) {\r | |
98 | url = url.substring(0, index);\r | |
99 | }\r | |
100 | \r | |
101 | for (i = 0; i < len; ++i) {\r | |
102 | simlet = simlets[i];\r | |
103 | simUrl = simlet.url;\r | |
104 | if (simUrl instanceof RegExp) {\r | |
105 | match = simUrl.test(url);\r | |
106 | } else {\r | |
107 | match = simUrl === url;\r | |
108 | }\r | |
109 | if (match) {\r | |
110 | return simlet;\r | |
111 | }\r | |
112 | }\r | |
113 | \r | |
114 | return me.defaultSimlet;\r | |
115 | },\r | |
116 | \r | |
117 | getXhr: function (method, url, options, async) {\r | |
118 | var simlet = this.getSimlet(url);\r | |
119 | \r | |
120 | if (simlet) {\r | |
121 | return simlet.openRequest(method, url, options, async);\r | |
122 | }\r | |
123 | \r | |
124 | return null;\r | |
125 | },\r | |
126 | \r | |
127 | /**\r | |
128 | * Initializes this singleton and applies configuration options.\r | |
129 | * @param {Object} config An optional object with configuration properties to apply.\r | |
130 | * @return {Ext.ux.ajax.SimManager} this\r | |
131 | */\r | |
132 | init: function (config) {\r | |
133 | var me = this;\r | |
134 | \r | |
135 | Ext.apply(me, config);\r | |
136 | \r | |
137 | if (!me.ready) {\r | |
138 | me.ready = true;\r | |
139 | \r | |
140 | if (!('defaultSimlet' in me)) {\r | |
141 | me.defaultSimlet = new Ext.ux.ajax.Simlet({\r | |
142 | status: 404,\r | |
143 | statusText: 'Not Found'\r | |
144 | });\r | |
145 | }\r | |
146 | \r | |
147 | me._openRequest = Ext.data.Connection.prototype.openRequest;\r | |
148 | \r | |
149 | Ext.data.request.Ajax.override({\r | |
150 | openRequest: function (options, requestOptions, async) {\r | |
151 | var xhr = !options.nosim &&\r | |
152 | me.getXhr(requestOptions.method, requestOptions.url, options, async);\r | |
153 | if (!xhr) {\r | |
154 | xhr = this.callParent(arguments);\r | |
155 | }\r | |
156 | return xhr;\r | |
157 | }\r | |
158 | });\r | |
159 | \r | |
160 | if (Ext.data.JsonP) {\r | |
161 | Ext.data.JsonP.self.override({\r | |
162 | createScript: function (url, params, options) {\r | |
163 | var fullUrl = Ext.urlAppend(url, Ext.Object.toQueryString(params)),\r | |
164 | script = !options.nosim &&\r | |
165 | me.getXhr('GET', fullUrl, options, true);\r | |
166 | \r | |
167 | if (!script) {\r | |
168 | script = this.callParent(arguments);\r | |
169 | }\r | |
170 | \r | |
171 | return script;\r | |
172 | },\r | |
173 | \r | |
174 | loadScript: function (request) {\r | |
175 | var script = request.script;\r | |
176 | if (script.simlet) {\r | |
177 | script.jsonpCallback = request.params[request.callbackKey];\r | |
178 | script.send(null);\r | |
179 | \r | |
180 | // Ext.data.JsonP will attempt dom removal of a script tag, so emulate its presence\r | |
181 | request.script = document.createElement('script');\r | |
182 | } else {\r | |
183 | this.callParent(arguments);\r | |
184 | }\r | |
185 | }\r | |
186 | });\r | |
187 | }\r | |
188 | }\r | |
189 | \r | |
190 | return me;\r | |
191 | },\r | |
192 | \r | |
193 | openRequest: function (method, url, async) {\r | |
194 | var opt = {\r | |
195 | method: method,\r | |
196 | url: url\r | |
197 | };\r | |
198 | return this._openRequest.call(Ext.data.Connection.prototype, {}, opt, async);\r | |
199 | },\r | |
200 | \r | |
201 | /**\r | |
202 | * Registeres one or more {@link Ext.ux.ajax.Simlet} instances.\r | |
203 | * @param {Array/Object} simlet Either a {@link Ext.ux.ajax.Simlet} instance or config, an Array\r | |
204 | * of such elements or an Object keyed by URL with values that are {@link Ext.ux.ajax.Simlet}\r | |
205 | * instances or configs.\r | |
206 | */\r | |
207 | register: function (simlet) {\r | |
208 | var me = this;\r | |
209 | \r | |
210 | me.init();\r | |
211 | \r | |
212 | function reg (one) {\r | |
213 | var simlet = one;\r | |
214 | if (!simlet.isSimlet) {\r | |
215 | simlet = Ext.create('simlet.' + (simlet.type || simlet.stype || me.defaultType), one);\r | |
216 | }\r | |
217 | me.simlets.push(simlet);\r | |
218 | simlet.manager = me;\r | |
219 | }\r | |
220 | \r | |
221 | if (Ext.isArray(simlet)) {\r | |
222 | Ext.each(simlet, reg);\r | |
223 | } else if (simlet.isSimlet || simlet.url) {\r | |
224 | reg(simlet);\r | |
225 | } else {\r | |
226 | Ext.Object.each(simlet, function (url, s) {\r | |
227 | s.url = url;\r | |
228 | reg(s);\r | |
229 | });\r | |
230 | }\r | |
231 | \r | |
232 | return me;\r | |
233 | }\r | |
234 | });\r |