- var JSONPRequest = Y.JSONPRequest,
- getByPath = Y.Object.getValue,
- noop = function () {};
-
- /**
- * Adds support for parsing complex callback identifiers from the jsonp url.
- * This includes callback=foo[1]bar.baz["goo"] as well as referencing methods
- * in the YUI instance.
- *
- * @module jsonp
- * @submodule jsonp-url
- * @for JSONPRequest
- */
-
- Y.mix(JSONPRequest.prototype, {
- /**
- * RegExp used by the default URL formatter to insert the generated callback
- * name into the JSONP url. Looks for a query param callback=. If a value
- * is assigned, it will be clobbered.
- *
- * @property _pattern
- * @type RegExp
- * @default /\bcallback=.*?(?=&|$)/i
- * @protected
- */
- _pattern: /\bcallback=(.*?)(?=&|$)/i,
-
- /**
- * Template used by the default URL formatter to add the callback function
- * name to the url.
- *
- * @property _template
- * @type String
- * @default "callback={callback}"
- * @protected
- */
- _template: "callback={callback}",
-
- /**
- * <p>Parses the url for a callback named explicitly in the string.
- * Override this if the target JSONP service uses a different query
- * parameter or url format.</p>
- *
- * <p>If the callback is declared inline, the corresponding function will
- * be returned. Otherwise null.</p>
- *
- * @method _defaultCallback
- * @param url {String} the url to search in
- * @return {Function} the callback function if found, or null
- * @protected
- */
- _defaultCallback: function (url) {
- var match = url.match(this._pattern),
- keys = [],
- i = 0,
- locator, path, callback;
-
- if (match) {
- // Strip the ["string keys"] and [1] array indexes
- locator = match[1]
- .replace(/\[(['"])(.*?)\1\]/g,
- function (x, $1, $2) {
- keys[i] = $2;
- return '.@' + (i++);
- })
- .replace(/\[(\d+)\]/g,
- function (x, $1) {
- /*jslint bitwise: true */
- keys[i] = parseInt($1, 10) | 0;
- return '.@' + (i++);
- })
- .replace(/^\./, ''); // remove leading dot
-
- // Validate against problematic characters.
- if (!/[^\w\.\$@]/.test(locator)) {
- path = locator.split('.');
- for (i = path.length - 1; i >= 0; --i) {
- if (path[i].charAt(0) === '@') {
- path[i] = keys[parseInt(path[i].substr(1), 10)];
- }
- }
-
- // First look for a global function, then the Y, then try the Y
- // again from the second token (to support "callback=Y.handler")
- callback = getByPath(Y.config.win, path) ||
- getByPath(Y, path) ||
- getByPath(Y, path.slice(1));
- }
- }
-
- return callback || noop;
- },
-
- /**
- * URL formatter that looks for callback= in the url and appends it
- * if not present. The supplied proxy name will be assigned to the query
- * param. Override this method by passing a function as the
- * "format" property in the config object to the constructor.
- *
- * @method _format
- * @param url { String } the original url
- * @param proxy {String} the function name that will be used as a proxy to
- * the configured callback methods.
- * @return {String} fully qualified JSONP url
- * @protected
- */
- _format: function (url, proxy) {
- var callbackRE = /\{callback\}/,
- callback, lastChar;
-
- if (callbackRE.test(url)) {
- return url.replace(callbackRE, proxy);
- }
-
- callback = this._template.replace(callbackRE, proxy);
-
- if (this._pattern.test(url)) {
- return url.replace(this._pattern, callback);
- } else {
- lastChar = url.slice(-1);
- if (lastChar !== '&' && lastChar !== '?') {
- url += (url.indexOf('?') > -1) ? '&' : '?';
- }
- return url + callback;
- }
- }
-
- }, true);
-
-