Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / examples / ux / ajax / SimManager.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  * @author Don Griffin
17  * @class Ext.ux.ajax.SimManager
18  *
19  * This singleton manages simulated Ajax responses. This allows application logic to be
20  * written unaware that its Ajax calls are being handled by simulations ("simlets"). This
21  * is currently done by hooking {@link Ext.data.Connection} methods, so all users of that
22  * class (and {@link Ext.Ajax} since it is a derived class) qualify for simulation.
23  *
24  * The requires hooks are inserted when either the {@link #init} method is called or the
25  * first {@link Simlet} is registered. For example:
26  *
27  *      Ext.onReady(function () {
28  *          initAjaxSim();
29  *
30  *          // normal stuff
31  *      });
32  *
33  *      function initAjaxSim () {
34  *          Ext.ux.ajax.SimManager.init({
35  *              delay: 300
36  *          }).register({
37  *              '/app/data/url': {
38  *                  stype: 'json',  // use JsonSimlet (stype is like xtype for components)
39  *                  data: [
40  *                      { foo: 42, bar: 'abc' },
41  *                      ...
42  *                  ]
43  *              }
44  *          });
45  *      }
46  *
47  * As many URL's as desired can be registered and associated with a {@link Simlet}. To make
48  * non-simulated Ajax requests once this singleton is initialized, add a `nosim:true` option
49  * to the Ajax options:
50  *
51  *      Ext.Ajax.request({
52  *          url: 'page.php',
53  *          nosim: true, // ignored by normal Ajax request
54  *          params: {
55  *              id: 1
56  *          },
57  *          success: function(response){
58  *              var text = response.responseText;
59  *              // process server response here
60  *          }
61  *      });
62  *
63  * @markdown
64  */
65 Ext.define('Ext.ux.ajax.SimManager', {
66     singleton: true,
67
68     requires: [
69         'Ext.data.Connection',
70         'Ext.ux.ajax.SimXhr',
71         'Ext.ux.ajax.Simlet',
72         'Ext.ux.ajax.JsonSimlet'
73     ],
74
75     /**
76      * @cfg {Ext.ux.ajax.Simlet} defaultSimlet
77      * The {@link Simlet} instance to use for non-matching URL's. By default, this will
78      * return 404. Set this to null to use real Ajax calls for non-matching URL's.
79      */
80
81     /**
82      * @cfg {String} defaultType
83      * The default `stype` to apply to generic {@link Simlet} configuration objects. The
84      * default is 'basic'.
85      */
86     defaultType: 'basic',
87
88     /**
89      * @cfg {Number} delay
90      * The number of milliseconds to delay before delivering a response to an async request.
91      */
92     delay: 150,
93
94     /**
95      * @prop {Boolean} ready
96      * True once this singleton has initialized and applied its Ajax hooks.
97      * @private
98      */
99     ready: false,
100
101     constructor: function () {
102         this.simlets = {};
103     },
104
105     getXhr: function (url) {
106         // Strip down to base URL (no query parameters or hash):
107         var me = this,
108             index = url.indexOf('?');
109
110         if (index < 0) {
111             index = url.indexOf('#');
112         }
113         if (index > 0) {
114             url = url.substring(0, index);
115         }
116
117         var simlet = me.simlets[url] || me.defaultSimlet;
118
119         if (simlet) {
120             return Ext.create('Ext.ux.ajax.SimXhr', { mgr: me, simlet: simlet });
121         }
122         return null;
123     },
124
125     /**
126      * Initializes this singleton and applies configuration options.
127      * @param {Object} config An optional object with configuration properties to apply.
128      * @return {SimManager} this
129      * @markdown
130      */
131     init: function (config) {
132         var me = this,
133             proto = Ext.data.Connection.prototype,
134             newXhr = proto.getXhrInstance,
135             setOptions = proto.setOptions,
136             url;
137
138         Ext.apply(me, config);
139
140         if (!me.ready) {
141             me.ready = true;
142
143             if (!('defaultSimlet' in me)) {
144                 me.defaultSimlet = Ext.create('Ext.ux.ajax.Simlet', {
145                     status: 404,
146                     statusText: 'Not Found'
147                 });
148             }
149
150             proto.getXhrInstance = function () {
151                 // the only way 'url' will be null is for nosim...
152                 var xhr = url && me.getXhr(url);
153                 if (!xhr) {
154                     xhr = newXhr.call(this);
155                 }
156                 return xhr;
157             };
158
159             proto.setOptions = function (options) {
160                 var ret = setOptions.apply(this, arguments);
161                 // remember the URL so we can give the right Simlet to the SimXhr...
162                 url = options.nosim ? null : ret.url;
163                 return ret;
164             };
165         }
166
167         return me;
168     },
169
170     /**
171      * Registeres one or more {@link Simlet} instances.
172      * @param {Array/Object} simlet Either a {@link Simlet} instance or config, an Array
173      * of such elements or an Object keyed by URL with values that are {@link Simlet}
174      * instances or configs.
175      * @markdown
176      */
177     register: function (simlet) {
178         var me = this,
179             i, n;
180
181         me.init();
182
183         function reg (one) {
184             var simlet = one;
185             if (!simlet.isSimlet) {
186                 simlet = Ext.create('simlet.' + (simlet.stype || me.defaultType), one);
187             }
188             me.simlets[one.url] = simlet;
189         }
190
191         if (Ext.isArray(simlet)) {
192             Ext.each(simlet, reg);
193         } else if (simlet.isSimlet || simlet.url) {
194             reg(simlet);
195         } else {
196             Ext.Object.each(simlet, function (url, s) {
197                 s.url = url;
198                 reg(s);
199             });
200         }
201
202         return me;
203     }
204 });
205