esri-leaflet
Version:
Leaflet plugins for consuming ArcGIS Online and ArcGIS Server services.
223 lines (177 loc) • 6.33 kB
JavaScript
import L from 'leaflet';
import Support from './Support';
import { warn } from './Util';
var callbacks = 0;
function serialize (params) {
var data = '';
params.f = params.f || 'json';
for (var key in params) {
if (params.hasOwnProperty(key)) {
var param = params[key];
var type = Object.prototype.toString.call(param);
var value;
if (data.length) {
data += '&';
}
if (type === '[object Array]') {
value = (Object.prototype.toString.call(param[0]) === '[object Object]') ? JSON.stringify(param) : param.join(',');
} else if (type === '[object Object]') {
value = JSON.stringify(param);
} else if (type === '[object Date]') {
value = param.valueOf();
} else {
value = param;
}
data += encodeURIComponent(key) + '=' + encodeURIComponent(value);
}
}
return data;
}
function createRequest (callback, context) {
var httpRequest = new window.XMLHttpRequest();
httpRequest.onerror = function (e) {
httpRequest.onreadystatechange = L.Util.falseFn;
callback.call(context, {
error: {
code: 500,
message: 'XMLHttpRequest error'
}
}, null);
};
httpRequest.onreadystatechange = function () {
var response;
var error;
if (httpRequest.readyState === 4) {
try {
response = JSON.parse(httpRequest.responseText);
} catch (e) {
response = null;
error = {
code: 500,
message: 'Could not parse response as JSON. This could also be caused by a CORS or XMLHttpRequest error.'
};
}
if (!error && response.error) {
error = response.error;
response = null;
}
httpRequest.onerror = L.Util.falseFn;
callback.call(context, error, response);
}
};
httpRequest.ontimeout = function () {
this.onerror();
};
return httpRequest;
}
function xmlHttpPost (url, params, callback, context) {
var httpRequest = createRequest(callback, context);
httpRequest.open('POST', url);
if (typeof context !== 'undefined' && context !== null) {
if (typeof context.options !== 'undefined') {
httpRequest.timeout = context.options.timeout;
}
}
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
httpRequest.send(serialize(params));
return httpRequest;
}
function xmlHttpGet (url, params, callback, context) {
var httpRequest = createRequest(callback, context);
httpRequest.open('GET', url + '?' + serialize(params), true);
if (typeof context !== 'undefined' && context !== null) {
if (typeof context.options !== 'undefined') {
httpRequest.timeout = context.options.timeout;
}
}
httpRequest.send(null);
return httpRequest;
}
// AJAX handlers for CORS (modern browsers) or JSONP (older browsers)
export function request (url, params, callback, context) {
var paramString = serialize(params);
var httpRequest = createRequest(callback, context);
var requestLength = (url + '?' + paramString).length;
// get around ie10/11 bug which requires that the request be opened before a timeout is applied
if (requestLength <= 2000 && Support.cors) {
httpRequest.open('GET', url + '?' + paramString);
} else if (requestLength > 2000 && Support.cors) {
httpRequest.open('POST', url);
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
if (typeof context !== 'undefined' && context !== null) {
if (typeof context.options !== 'undefined') {
httpRequest.timeout = context.options.timeout;
}
}
// request is less then 2000 characters and the browser supports CORS, make GET request with XMLHttpRequest
if (requestLength <= 2000 && Support.cors) {
httpRequest.send(null);
// request is less more then 2000 characters and the browser supports CORS, make POST request with XMLHttpRequest
} else if (requestLength > 2000 && Support.cors) {
httpRequest.send(paramString);
// request is less more then 2000 characters and the browser does not support CORS, make a JSONP request
} else if (requestLength <= 2000 && !Support.cors) {
return jsonp(url, params, callback, context);
// request is longer then 2000 characters and the browser does not support CORS, log a warning
} else {
warn('a request to ' + url + ' was longer then 2000 characters and this browser cannot make a cross-domain post request. Please use a proxy http://esri.github.io/esri-leaflet/api-reference/request.html');
return;
}
return httpRequest;
}
export function jsonp (url, params, callback, context) {
window._EsriLeafletCallbacks = window._EsriLeafletCallbacks || {};
var callbackId = 'c' + callbacks;
params.callback = 'window._EsriLeafletCallbacks.' + callbackId;
window._EsriLeafletCallbacks[callbackId] = function (response) {
if (window._EsriLeafletCallbacks[callbackId] !== true) {
var error;
var responseType = Object.prototype.toString.call(response);
if (!(responseType === '[object Object]' || responseType === '[object Array]')) {
error = {
error: {
code: 500,
message: 'Expected array or object as JSONP response'
}
};
response = null;
}
if (!error && response.error) {
error = response;
response = null;
}
callback.call(context, error, response);
window._EsriLeafletCallbacks[callbackId] = true;
}
};
var script = L.DomUtil.create('script', null, document.body);
script.type = 'text/javascript';
script.src = url + '?' + serialize(params);
script.id = callbackId;
callbacks++;
return {
id: callbackId,
url: script.src,
abort: function () {
window._EsriLeafletCallbacks._callback[callbackId]({
code: 0,
message: 'Request aborted.'
});
}
};
}
var get = ((Support.cors) ? xmlHttpGet : jsonp);
get.CORS = xmlHttpGet;
get.JSONP = jsonp;
// choose the correct AJAX handler depending on CORS support
export { get };
// always use XMLHttpRequest for posts
export { xmlHttpPost as post };
// export the Request object to call the different handlers for debugging
export var Request = {
request: request,
get: get,
post: xmlHttpPost
};
export default Request;