UNPKG

ol

Version:

OpenLayers mapping library

182 lines (175 loc) 6.11 kB
/** * @module ol/featureloader */ import {VOID} from './functions.js'; /** * * @type {boolean} * @private */ let withCredentials = false; /** * {@link module:ol/source/Vector~VectorSource} sources use a function of this type to * load features. * * This function takes up to 5 arguments. These are an {@link module:ol/extent~Extent} representing * the area to be loaded, a `{number}` representing the resolution (map units per pixel), a * {@link module:ol/proj/Projection~Projection} for the projection, an optional success callback that should get * the loaded features passed as an argument and an optional failure callback with no arguments. If * the callbacks are not used, the corresponding vector source will not fire `'featuresloadend'` and * `'featuresloaderror'` events. `this` within the function is bound to the * {@link module:ol/source/Vector~VectorSource} it's called from. * * The function is responsible for loading the features and adding them to the * source. * * @template {import("./Feature.js").FeatureLike} [FeatureType=import("./Feature.js").FeatureLike] * @typedef {( * extent: import("./extent.js").Extent, * resolution: number, * projection: import("./proj/Projection.js").default, * success?: (features: Array<FeatureType>) => void, * failure?: () => void) => void} FeatureLoader * @api */ /** * {@link module:ol/source/Vector~VectorSource} sources use a function of this type to * get the url to load features from. * * This function takes an {@link module:ol/extent~Extent} representing the area * to be loaded, a `{number}` representing the resolution (map units per pixel) * and an {@link module:ol/proj/Projection~Projection} for the projection as * arguments and returns a `{string}` representing the URL. * @typedef {function(import("./extent.js").Extent, number, import("./proj/Projection.js").default): string} FeatureUrlFunction * @api */ /** * @template {import("./Feature.js").FeatureLike} [FeatureType=import("./Feature.js").default] * @param {string|FeatureUrlFunction} url Feature URL service. * @param {import("./format/Feature.js").default<FeatureType>} format Feature format. * @param {import("./extent.js").Extent} extent Extent. * @param {number} resolution Resolution. * @param {import("./proj/Projection.js").default} projection Projection. * @param {function(Array<FeatureType>, import("./proj/Projection.js").default): void} success Success * Function called with the loaded features and optionally with the data projection. * @param {function(): void} failure Failure * Function called when loading failed. */ export function loadFeaturesXhr( url, format, extent, resolution, projection, success, failure, ) { const xhr = new XMLHttpRequest(); xhr.open( 'GET', typeof url === 'function' ? url(extent, resolution, projection) : url, true, ); if (format.getType() == 'arraybuffer') { xhr.responseType = 'arraybuffer'; } xhr.withCredentials = withCredentials; /** * @param {Event} event Event. * @private */ xhr.onload = function (event) { // status will be 0 for file:// urls if (!xhr.status || (xhr.status >= 200 && xhr.status < 300)) { const type = format.getType(); try { /** @type {Document|Node|Object|string|undefined} */ let source; if (type == 'text' || type == 'json') { source = xhr.responseText; } else if (type == 'xml') { source = xhr.responseXML || xhr.responseText; } else if (type == 'arraybuffer') { source = /** @type {ArrayBuffer} */ (xhr.response); } if (source) { success( /** @type {Array<FeatureType>} */ ( format.readFeatures(source, { extent: extent, featureProjection: projection, }) ), format.readProjection(source), ); } else { failure(); } } catch { failure(); } } else { failure(); } }; /** * @private */ xhr.onerror = failure; xhr.send(); } /** * Create an XHR feature loader for a `url` and `format`. The feature loader * loads features (with XHR), parses the features, and adds them to the * vector source. * * @template {import("./Feature.js").FeatureLike} [FeatureType=import("./Feature.js").default] * @param {string|FeatureUrlFunction} url Feature URL service. * @param {import("./format/Feature.js").default<FeatureType>} format Feature format. * @return {FeatureLoader<FeatureType>} The feature loader. * @api */ export function xhr(url, format) { /** * @param {import("./extent.js").Extent} extent Extent. * @param {number} resolution Resolution. * @param {import("./proj/Projection.js").default} projection Projection. * @param {function(Array<FeatureType>): void} [success] Success * Function called when loading succeeded. * @param {function(): void} [failure] Failure * Function called when loading failed. * @this {import("./source/Vector.js").default<FeatureType>} */ return function (extent, resolution, projection, success, failure) { loadFeaturesXhr( url, format, extent, resolution, projection, /** * @param {Array<FeatureType>} features The loaded features. * @param {import("./proj/Projection.js").default} dataProjection Data * projection. */ (features, dataProjection) => { this.addFeatures(features); if (success !== undefined) { success(features); } }, /* FIXME handle error */ failure ? failure : VOID, ); }; } /** * Setter for the withCredentials configuration for the XHR. * * @param {boolean} xhrWithCredentials The value of withCredentials to set. * Compare https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/ * @api */ export function setWithCredentials(xhrWithCredentials) { withCredentials = xhrWithCredentials; }