/*global define*/ define([ './defaultValue', './DeveloperError', '../ThirdParty/when' ], function( defaultValue, DeveloperError, when) { "use strict"; function pushQueryParameter(array, name, value) { array.push(encodeURIComponent(name) + '=' + encodeURIComponent(value)); } /** * Requests a resource using JSONP. * * @exports jsonp * * @param {String} url The URL to request. * @param {Object} [options.parameters] Any extra query parameters to append to the URL. * @param {String} [options.callbackParameterName='callback'] The callback parameter name that the server expects. * @param {Object} [options.proxy] A proxy to use for the request. This object is expected to have a getURL function which returns the proxied URL, if needed. * * @returns {Object} a promise that will resolve to the requested data when loaded. * * @see <a href='http://wiki.commonjs.org/wiki/Promises/A'>CommonJS Promises/A</a> * * @example * // load a data asynchronously * jsonp('some/webservice').then(function(data) { * // use the loaded data * }, function() { * // an error occurred * }); */ var jsonp = function(url, options) { if (typeof url === 'undefined') { throw new DeveloperError('url is required.'); } options = defaultValue(options, defaultValue.EMPTY_OBJECT); var deferred = when.defer(); //generate a unique function name var functionName; do { functionName = 'jsonp' + Math.random().toString().substring(2, 8); } while (typeof window[functionName] !== 'undefined'); //assign a function with that name in the global scope window[functionName] = function(data) { deferred.resolve(data); try { delete window[functionName]; } catch (e) { window[functionName] = undefined; } }; var callbackParameterName = defaultValue(options.callbackParameterName, 'callback'); var queryParts = []; pushQueryParameter(queryParts, callbackParameterName, functionName); var parameters = defaultValue(options.parameters, defaultValue.EMPTY_OBJECT); for ( var name in parameters) { if (parameters.hasOwnProperty(name)) { pushQueryParameter(queryParts, name, parameters[name]); } } if (queryParts.length > 0) { if (url.indexOf('?') === -1) { url += '?'; } else { url += '&'; } url += queryParts.join('&'); } var proxy = options.proxy; if (typeof proxy !== 'undefined') { url = proxy.getURL(url); } jsonp.loadAndExecuteScript(url, functionName, deferred); return deferred.promise; }; // This is broken out into a separate function so that it can be mocked for testing purposes. jsonp.loadAndExecuteScript = function(url, functionName, deferred) { var script = document.createElement('script'); script.async = true; script.src = url; var head = document.getElementsByTagName('head')[0]; script.onload = function() { script.onload = undefined; head.removeChild(script); }; script.onerror = function(e) { deferred.reject(e); }; head.appendChild(script); }; jsonp.defaultLoadAndExecuteScript = jsonp.loadAndExecuteScript; return jsonp; });