NOBUG: Fixed file access permissions
[moodle.git] / lib / yuilib / 3.13.0 / jsonp / jsonp-debug.js
blobfe31ef2305d83b3267c195b0f1b2b236ebb51d90
1 /*
2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
8 YUI.add('jsonp', function (Y, NAME) {
10 var isFunction = Y.Lang.isFunction;
12 /**
13  * <p>Provides a JSONPRequest class for repeated JSONP calls, and a convenience
14  * method Y.jsonp(url, callback) to instantiate and send a JSONP request.</p>
15  *
16  * <p>Both the constructor as well as the convenience function take two
17  * parameters: a url string and a callback.</p>
18  *
19  * <p>The url provided must include the placeholder string
20  * &quot;{callback}&quot; which will be replaced by a dynamically
21  * generated routing function to pass the data to your callback function.
22  * An example url might look like
23  * &quot;http://example.com/service?callback={callback}&quot;.</p>
24  *
25  * <p>The second parameter can be a callback function that accepts the JSON
26  * payload as its argument, or a configuration object supporting the keys:</p>
27  * <ul>
28  *   <li>on - map of callback subscribers
29  *      <ul>
30  *         <li>success - function handler for successful transmission</li>
31  *         <li>failure - function handler for failed transmission</li>
32  *         <li>timeout - function handler for transactions that timeout</li>
33  *      </ul>
34  *  </li>
35  *  <li>format  - override function for inserting the proxy name in the url</li>
36  *  <li>timeout - the number of milliseconds to wait before giving up</li>
37  *  <li>context - becomes <code>this</code> in the callbacks</li>
38  *  <li>args    - array of subsequent parameters to pass to the callbacks</li>
39  *  <li>allowCache - use the same proxy name for all requests? (boolean)</li>
40  * </ul>
41  *
42  * @module jsonp
43  * @class JSONPRequest
44  * @constructor
45  * @param url {String} the url of the JSONP service
46  * @param callback {Object|Function} the default callback configuration or
47  *                                   success handler
48  */
49 function JSONPRequest() {
50     this._init.apply(this, arguments);
53 JSONPRequest.prototype = {
54     /**
55      * Set up the success and failure handlers and the regex pattern used
56      * to insert the temporary callback name in the url.
57      *
58      * @method _init
59      * @param url {String} the url of the JSONP service
60      * @param callback {Object|Function} Optional success callback or config
61      *                  object containing success and failure functions and
62      *                  the url regex.
63      * @protected
64      */
65     _init : function (url, callback) {
66         this.url = url;
68         /**
69          * Map of the number of requests currently pending responses per
70          * generated proxy.  Used to ensure the proxy is not flushed if the
71          * request times out and there is a timeout handler and success
72          * handler, and used by connections configured to allowCache to make
73          * sure the proxy isn't deleted until the last response has returned.
74          *
75          * @property _requests
76          * @private
77          * @type {Object}
78          */
79         this._requests = {};
81         /**
82          * Map of the number of timeouts received from the destination url
83          * by generated proxy.  Used to ensure the proxy is not flushed if the
84          * request times out and there is a timeout handler and success
85          * handler, and used by connections configured to allowCache to make
86          * sure the proxy isn't deleted until the last response has returned.
87          *
88          * @property _timeouts
89          * @private
90          * @type {Object}
91          */
92         this._timeouts = {};
94         // Accept a function, an object, or nothing
95         callback = (isFunction(callback)) ?
96             { on: { success: callback } } :
97             callback || {};
99         var subs = callback.on || {};
101         if (!subs.success) {
102             subs.success = this._defaultCallback(url, callback);
103         }
105         // Apply defaults and store
106         this._config = Y.merge({
107                 context: this,
108                 args   : [],
109                 format : this._format,
110                 allowCache: false
111             }, callback, { on: subs });
112     },
114     /**
115      * Override this method to provide logic to default the success callback if
116      * it is not provided at construction.  This is overridden by jsonp-url to
117      * parse the callback from the url string.
118      *
119      * @method _defaultCallback
120      * @param url {String} the url passed at construction
121      * @param config {Object} (optional) the config object passed at
122      *                        construction
123      * @return {Function}
124      */
125     _defaultCallback: function () {},
127     /**
128      * Issues the JSONP request.
129      *
130      * @method send
131      * @param args* {any} any additional arguments to pass to the url formatter
132      *              beyond the base url and the proxy function name
133      * @chainable
134      */
135     send : function () {
136         var self   = this,
137             args   = Y.Array(arguments, 0, true),
138             config = self._config,
139             proxy  = self._proxy || Y.guid(),
140             url;
142         // TODO: support allowCache as time value
143         if (config.allowCache) {
144             self._proxy = proxy;
145         }
147         if (self._requests[proxy] === undefined) {
148             self._requests[proxy] = 0;
149         }
150         if (self._timeouts[proxy] === undefined) {
151             self._timeouts[proxy] = 0;
152         }
153         self._requests[proxy]++;
155         Y.log('sending ' + proxy);
157         args.unshift(self.url, 'YUI.Env.JSONP.' + proxy);
158         url = config.format.apply(self, args);
160         if (!config.on.success) {
161             Y.log("No success handler defined.  Aborting JSONP request.", "warn", "jsonp");
162             return self;
163         }
165         function wrap(fn, isTimeout) {
166             return (isFunction(fn)) ?
167                 function (data) {
168                     var execute = true,
169                         counter = '_requests';
171                     //if (config.allowCache) {
172                         // A lot of wrangling to make sure timeouts result in
173                         // fewer success callbacks, but the proxy is properly
174                         // cleaned up.
175                         if (isTimeout) {
176                             ++self._timeouts[proxy];
177                             --self._requests[proxy];
178                             Y.log(proxy + ' timed out - timeouts(' + self._timeouts[proxy] + ') requests(' + self._requests[proxy] + ')');
179                         } else {
180                             if (!self._requests[proxy]) {
181                                 execute = false;
182                                 counter = '_timeouts';
183                             }
184                             --self[counter][proxy];
185                             Y.log(proxy + ' response received - timeouts(' + self._timeouts[proxy] + ') requests(' + self._requests[proxy] + ')');
186                         }
187                     //}
189                     if (!self._requests[proxy] && !self._timeouts[proxy]) {
190                         Y.log('deleting ' + proxy);
191                         delete YUI.Env.JSONP[proxy];
192                     }
194                     if (execute) {
195                         fn.apply(config.context, [data].concat(config.args));
196                     }
197                 } :
198                 null;
199         }
201         // Temporary un-sandboxed function alias
202         // TODO: queuing
203         YUI.Env.JSONP[proxy] = wrap(config.on.success);
205         // Y.Get transactions block each other by design, but can easily
206         //  be made non-blocking by just calling execute() on the transaction.
207         // https://github.com/yui/yui3/pull/393#issuecomment-11961608
208         Y.Get.js(url, {
209             onFailure : wrap(config.on.failure),
210             onTimeout : wrap(config.on.timeout, true),
211             timeout   : config.timeout,
212             charset   : config.charset,
213             attributes: config.attributes,
214             async     : config.async
215         }).execute();
217         return self;
218     },
220     /**
221      * Default url formatter.  Looks for callback= in the url and appends it
222      * if not present.  The supplied proxy name will be assigned to the query
223      * param.  Override this method by passing a function as the
224      * &quot;format&quot; property in the config object to the constructor.
225      *
226      * @method _format
227      * @param url { String } the original url
228      * @param proxy {String} the function name that will be used as a proxy to
229      *      the configured callback methods.
230      * @param args* {any} additional args passed to send()
231      * @return {String} fully qualified JSONP url
232      * @protected
233      */
234     _format: function (url, proxy) {
235         return url.replace(/\{callback\}/, proxy);
236     }
239 Y.JSONPRequest = JSONPRequest;
243  * @method jsonp
244  * @param url {String} the url of the JSONP service with the {callback}
245  *          placeholder where the callback function name typically goes.
246  * @param c {Function|Object} Callback function accepting the JSON payload
247  *          as its argument, or a configuration object (see above).
248  * @param args* {any} additional arguments to pass to send()
249  * @return {JSONPRequest}
250  * @static
251  * @for YUI
252  */
253 Y.jsonp = function (url,c) {
254     var req = new Y.JSONPRequest(url,c);
255     return req.send.apply(req, Y.Array(arguments, 2, true));
258 if (!YUI.Env.JSONP) {
259     YUI.Env.JSONP = {};
263 }, '3.13.0', {"requires": ["get", "oop"]});