UNPKG

ol-plot-enhanced

Version:
1,711 lines (1,514 loc) 1.36 MB
/*! * author: baxtergu <baxtergu@gmail.com> * ol-plot-enhanced v0.1.0 * build-time: 2020-7-23 10:44 * LICENSE: MIT * (c) 2019-2020 https://github.com/baxtergu/ol-plot */ (function () { 'use strict'; /** * @module ol/util */ /** * @return {?} Any return. */ function abstract() { return /** @type {?} */ ((function() { throw new Error('Unimplemented abstract method.'); })()); } /** * Counter for getUid. * @type {number} * @private */ var uidCounter_ = 0; /** * Gets a unique ID for an object. This mutates the object so that further calls * with the same object as a parameter returns the same value. Unique IDs are generated * as a strictly increasing sequence. Adapted from goog.getUid. * * @param {Object} obj The object to get the unique ID for. * @return {string} The unique ID for the object. * @function module:ol.getUid * @api */ function getUid(obj) { return obj.ol_uid || (obj.ol_uid = String(++uidCounter_)); } /** * OpenLayers version. * @type {string} */ var VERSION = '5.3.3'; /** * @module ol/AssertionError */ /** * Error object thrown when an assertion failed. This is an ECMA-262 Error, * extended with a `code` property. * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error. */ var AssertionError = /*@__PURE__*/(function (Error) { function AssertionError(code) { var path = 'v' + VERSION.split('-')[0]; var message = 'Assertion failed. See https://openlayers.org/en/' + path + '/doc/errors/#' + code + ' for details.'; Error.call(this, message); /** * Error code. The meaning of the code can be found on * https://openlayers.org/en/latest/doc/errors/ (replace `latest` with * the version found in the OpenLayers script's header comment if a version * other than the latest is used). * @type {number} * @api */ this.code = code; /** * @type {string} */ this.name = 'AssertionError'; // Re-assign message, see https://github.com/Rich-Harris/buble/issues/40 this.message = message; } if ( Error ) AssertionError.__proto__ = Error; AssertionError.prototype = Object.create( Error && Error.prototype ); AssertionError.prototype.constructor = AssertionError; return AssertionError; }(Error)); /** * @module ol/CollectionEventType */ /** * @enum {string} */ var CollectionEventType = { /** * Triggered when an item is added to the collection. * @event module:ol/Collection.CollectionEvent#add * @api */ ADD: 'add', /** * Triggered when an item is removed from the collection. * @event module:ol/Collection.CollectionEvent#remove * @api */ REMOVE: 'remove' }; /** * @module ol/ObjectEventType */ /** * @enum {string} */ var ObjectEventType = { /** * Triggered when a property is changed. * @event module:ol/Object.ObjectEvent#propertychange * @api */ PROPERTYCHANGE: 'propertychange' }; /** * @module ol/obj */ /** * Polyfill for Object.assign(). Assigns enumerable and own properties from * one or more source objects to a target object. * See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign. * * @param {!Object} target The target object. * @param {...Object} var_sources The source object(s). * @return {!Object} The modified target object. */ var assign = (typeof Object.assign === 'function') ? Object.assign : function(target, var_sources) { var arguments$1 = arguments; if (target === undefined || target === null) { throw new TypeError('Cannot convert undefined or null to object'); } var output = Object(target); for (var i = 1, ii = arguments.length; i < ii; ++i) { var source = arguments$1[i]; if (source !== undefined && source !== null) { for (var key in source) { if (source.hasOwnProperty(key)) { output[key] = source[key]; } } } } return output; }; /** * Removes all properties from an object. * @param {Object} object The object to clear. */ function clear(object) { for (var property in object) { delete object[property]; } } /** * Get an array of property values from an object. * @param {Object<K,V>} object The object from which to get the values. * @return {!Array<V>} The property values. * @template K,V */ function getValues(object) { var values = []; for (var property in object) { values.push(object[property]); } return values; } /** * Determine if an object has any properties. * @param {Object} object The object to check. * @return {boolean} The object is empty. */ function isEmpty(object) { var property; for (property in object) { return false; } return !property; } /** * @module ol/events */ /** * Key to use with {@link module:ol/Observable~Observable#unByKey}. * @typedef {Object} EventsKey * @property {Object} [bindTo] * @property {ListenerFunction} [boundListener] * @property {boolean} callOnce * @property {number} [deleteIndex] * @property {ListenerFunction} listener * @property {import("./events/Target.js").EventTargetLike} target * @property {string} type * @api */ /** * Listener function. This function is called with an event object as argument. * When the function returns `false`, event propagation will stop. * * @typedef {function((Event|import("./events/Event.js").default)): (void|boolean)} ListenerFunction * @api */ /** * @param {EventsKey} listenerObj Listener object. * @return {ListenerFunction} Bound listener. */ function bindListener(listenerObj) { var boundListener = function(evt) { var listener = listenerObj.listener; var bindTo = listenerObj.bindTo || listenerObj.target; if (listenerObj.callOnce) { unlistenByKey(listenerObj); } return listener.call(bindTo, evt); }; listenerObj.boundListener = boundListener; return boundListener; } /** * Finds the matching {@link module:ol/events~EventsKey} in the given listener * array. * * @param {!Array<!EventsKey>} listeners Array of listeners. * @param {!Function} listener The listener function. * @param {Object=} opt_this The `this` value inside the listener. * @param {boolean=} opt_setDeleteIndex Set the deleteIndex on the matching * listener, for {@link module:ol/events~unlistenByKey}. * @return {EventsKey|undefined} The matching listener object. */ function findListener(listeners, listener, opt_this, opt_setDeleteIndex) { var listenerObj; for (var i = 0, ii = listeners.length; i < ii; ++i) { listenerObj = listeners[i]; if (listenerObj.listener === listener && listenerObj.bindTo === opt_this) { if (opt_setDeleteIndex) { listenerObj.deleteIndex = i; } return listenerObj; } } return undefined; } /** * @param {import("./events/Target.js").EventTargetLike} target Target. * @param {string} type Type. * @return {Array<EventsKey>|undefined} Listeners. */ function getListeners(target, type) { var listenerMap = getListenerMap(target); return listenerMap ? listenerMap[type] : undefined; } /** * Get the lookup of listeners. * @param {Object} target Target. * @param {boolean=} opt_create If a map should be created if it doesn't exist. * @return {!Object<string, Array<EventsKey>>} Map of * listeners by event type. */ function getListenerMap(target, opt_create) { var listenerMap = target.ol_lm; if (!listenerMap && opt_create) { listenerMap = target.ol_lm = {}; } return listenerMap; } /** * Remove the listener map from a target. * @param {Object} target Target. */ function removeListenerMap(target) { delete target.ol_lm; } /** * Clean up all listener objects of the given type. All properties on the * listener objects will be removed, and if no listeners remain in the listener * map, it will be removed from the target. * @param {import("./events/Target.js").EventTargetLike} target Target. * @param {string} type Type. */ function removeListeners(target, type) { var listeners = getListeners(target, type); if (listeners) { for (var i = 0, ii = listeners.length; i < ii; ++i) { /** @type {import("./events/Target.js").default} */ (target). removeEventListener(type, listeners[i].boundListener); clear(listeners[i]); } listeners.length = 0; var listenerMap = getListenerMap(target); if (listenerMap) { delete listenerMap[type]; if (Object.keys(listenerMap).length === 0) { removeListenerMap(target); } } } } /** * Registers an event listener on an event target. Inspired by * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html * * This function efficiently binds a `listener` to a `this` object, and returns * a key for use with {@link module:ol/events~unlistenByKey}. * * @param {import("./events/Target.js").EventTargetLike} target Event target. * @param {string} type Event type. * @param {ListenerFunction} listener Listener. * @param {Object=} opt_this Object referenced by the `this` keyword in the * listener. Default is the `target`. * @param {boolean=} opt_once If true, add the listener as one-off listener. * @return {EventsKey} Unique key for the listener. */ function listen(target, type, listener, opt_this, opt_once) { var listenerMap = getListenerMap(target, true); var listeners = listenerMap[type]; if (!listeners) { listeners = listenerMap[type] = []; } var listenerObj = findListener(listeners, listener, opt_this, false); if (listenerObj) { if (!opt_once) { // Turn one-off listener into a permanent one. listenerObj.callOnce = false; } } else { listenerObj = /** @type {EventsKey} */ ({ bindTo: opt_this, callOnce: !!opt_once, listener: listener, target: target, type: type }); /** @type {import("./events/Target.js").default} */ (target). addEventListener(type, bindListener(listenerObj)); listeners.push(listenerObj); } return listenerObj; } /** * Registers a one-off event listener on an event target. Inspired by * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html * * This function efficiently binds a `listener` as self-unregistering listener * to a `this` object, and returns a key for use with * {@link module:ol/events~unlistenByKey} in case the listener needs to be * unregistered before it is called. * * When {@link module:ol/events~listen} is called with the same arguments after this * function, the self-unregistering listener will be turned into a permanent * listener. * * @param {import("./events/Target.js").EventTargetLike} target Event target. * @param {string} type Event type. * @param {ListenerFunction} listener Listener. * @param {Object=} opt_this Object referenced by the `this` keyword in the * listener. Default is the `target`. * @return {EventsKey} Key for unlistenByKey. */ function listenOnce(target, type, listener, opt_this) { return listen(target, type, listener, opt_this, true); } /** * Unregisters an event listener on an event target. Inspired by * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html * * To return a listener, this function needs to be called with the exact same * arguments that were used for a previous {@link module:ol/events~listen} call. * * @param {import("./events/Target.js").EventTargetLike} target Event target. * @param {string} type Event type. * @param {ListenerFunction} listener Listener. * @param {Object=} opt_this Object referenced by the `this` keyword in the * listener. Default is the `target`. */ function unlisten(target, type, listener, opt_this) { var listeners = getListeners(target, type); if (listeners) { var listenerObj = findListener(listeners, listener, opt_this, true); if (listenerObj) { unlistenByKey(listenerObj); } } } /** * Unregisters event listeners on an event target. Inspired by * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html * * The argument passed to this function is the key returned from * {@link module:ol/events~listen} or {@link module:ol/events~listenOnce}. * * @param {EventsKey} key The key. */ function unlistenByKey(key) { if (key && key.target) { /** @type {import("./events/Target.js").default} */ (key.target). removeEventListener(key.type, key.boundListener); var listeners = getListeners(key.target, key.type); if (listeners) { var i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key); if (i !== -1) { listeners.splice(i, 1); } if (listeners.length === 0) { removeListeners(key.target, key.type); } } clear(key); } } /** * Unregisters all event listeners on an event target. Inspired by * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html * * @param {import("./events/Target.js").EventTargetLike} target Target. */ function unlistenAll(target) { var listenerMap = getListenerMap(target); if (listenerMap) { for (var type in listenerMap) { removeListeners(target, type); } } } /** * @module ol/Disposable */ /** * @classdesc * Objects that need to clean up after themselves. */ var Disposable = function Disposable() { /** * The object has already been disposed. * @type {boolean} * @private */ this.disposed_ = false; }; /** * Clean up. */ Disposable.prototype.dispose = function dispose () { if (!this.disposed_) { this.disposed_ = true; this.disposeInternal(); } }; /** * Extension point for disposable objects. * @protected */ Disposable.prototype.disposeInternal = function disposeInternal () {}; /** * @module ol/functions */ /** * Always returns true. * @returns {boolean} true. */ function TRUE() { return true; } /** * Always returns false. * @returns {boolean} false. */ function FALSE() { return false; } /** * A reusable function, used e.g. as a default for callbacks. * * @return {void} Nothing. */ function VOID() {} /** * @module ol/events/Event */ /** * @classdesc * Stripped down implementation of the W3C DOM Level 2 Event interface. * See https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface. * * This implementation only provides `type` and `target` properties, and * `stopPropagation` and `preventDefault` methods. It is meant as base class * for higher level events defined in the library, and works with * {@link module:ol/events/Target~Target}. */ var Event$1 = function Event(type) { /** * @type {boolean} */ this.propagationStopped; /** * The event type. * @type {string} * @api */ this.type = type; /** * The event target. * @type {Object} * @api */ this.target = null; }; /** * Stop event propagation. * @api */ Event$1.prototype.preventDefault = function preventDefault () { this.propagationStopped = true; }; /** * Stop event propagation. * @api */ Event$1.prototype.stopPropagation = function stopPropagation () { this.propagationStopped = true; }; /** * @param {Event|import("./Event.js").default} evt Event */ function stopPropagation(evt) { evt.stopPropagation(); } /** * @module ol/events/Target */ /** * @typedef {EventTarget|Target} EventTargetLike */ /** * @classdesc * A simplified implementation of the W3C DOM Level 2 EventTarget interface. * See https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget. * * There are two important simplifications compared to the specification: * * 1. The handling of `useCapture` in `addEventListener` and * `removeEventListener`. There is no real capture model. * 2. The handling of `stopPropagation` and `preventDefault` on `dispatchEvent`. * There is no event target hierarchy. When a listener calls * `stopPropagation` or `preventDefault` on an event object, it means that no * more listeners after this one will be called. Same as when the listener * returns false. */ var Target = /*@__PURE__*/(function (Disposable) { function Target() { Disposable.call(this); /** * @private * @type {!Object<string, number>} */ this.pendingRemovals_ = {}; /** * @private * @type {!Object<string, number>} */ this.dispatching_ = {}; /** * @private * @type {!Object<string, Array<import("../events.js").ListenerFunction>>} */ this.listeners_ = {}; } if ( Disposable ) Target.__proto__ = Disposable; Target.prototype = Object.create( Disposable && Disposable.prototype ); Target.prototype.constructor = Target; /** * @param {string} type Type. * @param {import("../events.js").ListenerFunction} listener Listener. */ Target.prototype.addEventListener = function addEventListener (type, listener) { var listeners = this.listeners_[type]; if (!listeners) { listeners = this.listeners_[type] = []; } if (listeners.indexOf(listener) === -1) { listeners.push(listener); } }; /** * Dispatches an event and calls all listeners listening for events * of this type. The event parameter can either be a string or an * Object with a `type` property. * * @param {{type: string, * target: (EventTargetLike|undefined), * propagationStopped: (boolean|undefined)}| * import("./Event.js").default|string} event Event object. * @return {boolean|undefined} `false` if anyone called preventDefault on the * event object or if any of the listeners returned false. * @api */ Target.prototype.dispatchEvent = function dispatchEvent (event) { var evt = typeof event === 'string' ? new Event$1(event) : event; var type = evt.type; evt.target = this; var listeners = this.listeners_[type]; var propagate; if (listeners) { if (!(type in this.dispatching_)) { this.dispatching_[type] = 0; this.pendingRemovals_[type] = 0; } ++this.dispatching_[type]; for (var i = 0, ii = listeners.length; i < ii; ++i) { if (listeners[i].call(this, evt) === false || evt.propagationStopped) { propagate = false; break; } } --this.dispatching_[type]; if (this.dispatching_[type] === 0) { var pendingRemovals = this.pendingRemovals_[type]; delete this.pendingRemovals_[type]; while (pendingRemovals--) { this.removeEventListener(type, VOID); } delete this.dispatching_[type]; } return propagate; } }; /** * @inheritDoc */ Target.prototype.disposeInternal = function disposeInternal () { unlistenAll(this); }; /** * Get the listeners for a specified event type. Listeners are returned in the * order that they will be called in. * * @param {string} type Type. * @return {Array<import("../events.js").ListenerFunction>} Listeners. */ Target.prototype.getListeners = function getListeners (type) { return this.listeners_[type]; }; /** * @param {string=} opt_type Type. If not provided, * `true` will be returned if this event target has any listeners. * @return {boolean} Has listeners. */ Target.prototype.hasListener = function hasListener (opt_type) { return opt_type ? opt_type in this.listeners_ : Object.keys(this.listeners_).length > 0; }; /** * @param {string} type Type. * @param {import("../events.js").ListenerFunction} listener Listener. */ Target.prototype.removeEventListener = function removeEventListener (type, listener) { var listeners = this.listeners_[type]; if (listeners) { var index = listeners.indexOf(listener); if (type in this.pendingRemovals_) { // make listener a no-op, and remove later in #dispatchEvent() listeners[index] = VOID; ++this.pendingRemovals_[type]; } else { listeners.splice(index, 1); if (listeners.length === 0) { delete this.listeners_[type]; } } } }; return Target; }(Disposable)); /** * @module ol/events/EventType */ /** * @enum {string} * @const */ var EventType = { /** * Generic change event. Triggered when the revision counter is increased. * @event module:ol/events/Event~Event#change * @api */ CHANGE: 'change', CLEAR: 'clear', CONTEXTMENU: 'contextmenu', CLICK: 'click', DBLCLICK: 'dblclick', DRAGENTER: 'dragenter', DRAGOVER: 'dragover', DROP: 'drop', ERROR: 'error', KEYDOWN: 'keydown', KEYPRESS: 'keypress', LOAD: 'load', MOUSEDOWN: 'mousedown', MOUSEMOVE: 'mousemove', MOUSEOUT: 'mouseout', MOUSEUP: 'mouseup', MOUSEWHEEL: 'mousewheel', MSPOINTERDOWN: 'MSPointerDown', RESIZE: 'resize', TOUCHSTART: 'touchstart', TOUCHMOVE: 'touchmove', TOUCHEND: 'touchend', WHEEL: 'wheel' }; /** * @module ol/Observable */ /** * @classdesc * Abstract base class; normally only used for creating subclasses and not * instantiated in apps. * An event target providing convenient methods for listener registration * and unregistration. A generic `change` event is always available through * {@link module:ol/Observable~Observable#changed}. * * @fires import("./events/Event.js").Event * @api */ var Observable = /*@__PURE__*/(function (EventTarget) { function Observable() { EventTarget.call(this); /** * @private * @type {number} */ this.revision_ = 0; } if ( EventTarget ) Observable.__proto__ = EventTarget; Observable.prototype = Object.create( EventTarget && EventTarget.prototype ); Observable.prototype.constructor = Observable; /** * Increases the revision counter and dispatches a 'change' event. * @api */ Observable.prototype.changed = function changed () { ++this.revision_; this.dispatchEvent(EventType.CHANGE); }; /** * Get the version number for this object. Each time the object is modified, * its version number will be incremented. * @return {number} Revision. * @api */ Observable.prototype.getRevision = function getRevision () { return this.revision_; }; /** * Listen for a certain type of event. * @param {string|Array<string>} type The event type or array of event types. * @param {function(?): ?} listener The listener function. * @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Unique key for the listener. If * called with an array of event types as the first argument, the return * will be an array of keys. * @api */ Observable.prototype.on = function on (type, listener) { if (Array.isArray(type)) { var len = type.length; var keys = new Array(len); for (var i = 0; i < len; ++i) { keys[i] = listen(this, type[i], listener); } return keys; } else { return listen(this, /** @type {string} */ (type), listener); } }; /** * Listen once for a certain type of event. * @param {string|Array<string>} type The event type or array of event types. * @param {function(?): ?} listener The listener function. * @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Unique key for the listener. If * called with an array of event types as the first argument, the return * will be an array of keys. * @api */ Observable.prototype.once = function once (type, listener) { if (Array.isArray(type)) { var len = type.length; var keys = new Array(len); for (var i = 0; i < len; ++i) { keys[i] = listenOnce(this, type[i], listener); } return keys; } else { return listenOnce(this, /** @type {string} */ (type), listener); } }; /** * Unlisten for a certain type of event. * @param {string|Array<string>} type The event type or array of event types. * @param {function(?): ?} listener The listener function. * @api */ Observable.prototype.un = function un (type, listener) { if (Array.isArray(type)) { for (var i = 0, ii = type.length; i < ii; ++i) { unlisten(this, type[i], listener); } return; } else { unlisten(this, /** @type {string} */ (type), listener); } }; return Observable; }(Target)); /** * @module ol/Object */ /** * @classdesc * Events emitted by {@link module:ol/Object~BaseObject} instances are instances of this type. */ var ObjectEvent = /*@__PURE__*/(function (Event) { function ObjectEvent(type, key, oldValue) { Event.call(this, type); /** * The name of the property whose value is changing. * @type {string} * @api */ this.key = key; /** * The old value. To get the new value use `e.target.get(e.key)` where * `e` is the event object. * @type {*} * @api */ this.oldValue = oldValue; } if ( Event ) ObjectEvent.__proto__ = Event; ObjectEvent.prototype = Object.create( Event && Event.prototype ); ObjectEvent.prototype.constructor = ObjectEvent; return ObjectEvent; }(Event$1)); /** * @classdesc * Abstract base class; normally only used for creating subclasses and not * instantiated in apps. * Most non-trivial classes inherit from this. * * This extends {@link module:ol/Observable} with observable * properties, where each property is observable as well as the object as a * whole. * * Classes that inherit from this have pre-defined properties, to which you can * add your owns. The pre-defined properties are listed in this documentation as * 'Observable Properties', and have their own accessors; for example, * {@link module:ol/Map~Map} has a `target` property, accessed with * `getTarget()` and changed with `setTarget()`. Not all properties are however * settable. There are also general-purpose accessors `get()` and `set()`. For * example, `get('target')` is equivalent to `getTarget()`. * * The `set` accessors trigger a change event, and you can monitor this by * registering a listener. For example, {@link module:ol/View~View} has a * `center` property, so `view.on('change:center', function(evt) {...});` would * call the function whenever the value of the center property changes. Within * the function, `evt.target` would be the view, so `evt.target.getCenter()` * would return the new center. * * You can add your own observable properties with * `object.set('prop', 'value')`, and retrieve that with `object.get('prop')`. * You can listen for changes on that property value with * `object.on('change:prop', listener)`. You can get a list of all * properties with {@link module:ol/Object~BaseObject#getProperties}. * * Note that the observable properties are separate from standard JS properties. * You can, for example, give your map object a title with * `map.title='New title'` and with `map.set('title', 'Another title')`. The * first will be a `hasOwnProperty`; the second will appear in * `getProperties()`. Only the second is observable. * * Properties can be deleted by using the unset method. E.g. * object.unset('foo'). * * @fires ObjectEvent * @api */ var BaseObject = /*@__PURE__*/(function (Observable) { function BaseObject(opt_values) { Observable.call(this); // Call {@link module:ol/util~getUid} to ensure that the order of objects' ids is // the same as the order in which they were created. This also helps to // ensure that object properties are always added in the same order, which // helps many JavaScript engines generate faster code. getUid(this); /** * @private * @type {!Object<string, *>} */ this.values_ = {}; if (opt_values !== undefined) { this.setProperties(opt_values); } } if ( Observable ) BaseObject.__proto__ = Observable; BaseObject.prototype = Object.create( Observable && Observable.prototype ); BaseObject.prototype.constructor = BaseObject; /** * Gets a value. * @param {string} key Key name. * @return {*} Value. * @api */ BaseObject.prototype.get = function get (key) { var value; if (this.values_.hasOwnProperty(key)) { value = this.values_[key]; } return value; }; /** * Get a list of object property names. * @return {Array<string>} List of property names. * @api */ BaseObject.prototype.getKeys = function getKeys () { return Object.keys(this.values_); }; /** * Get an object of all property names and values. * @return {Object<string, *>} Object. * @api */ BaseObject.prototype.getProperties = function getProperties () { return assign({}, this.values_); }; /** * @param {string} key Key name. * @param {*} oldValue Old value. */ BaseObject.prototype.notify = function notify (key, oldValue) { var eventType; eventType = getChangeEventType(key); this.dispatchEvent(new ObjectEvent(eventType, key, oldValue)); eventType = ObjectEventType.PROPERTYCHANGE; this.dispatchEvent(new ObjectEvent(eventType, key, oldValue)); }; /** * Sets a value. * @param {string} key Key name. * @param {*} value Value. * @param {boolean=} opt_silent Update without triggering an event. * @api */ BaseObject.prototype.set = function set (key, value, opt_silent) { if (opt_silent) { this.values_[key] = value; } else { var oldValue = this.values_[key]; this.values_[key] = value; if (oldValue !== value) { this.notify(key, oldValue); } } }; /** * Sets a collection of key-value pairs. Note that this changes any existing * properties and adds new ones (it does not remove any existing properties). * @param {Object<string, *>} values Values. * @param {boolean=} opt_silent Update without triggering an event. * @api */ BaseObject.prototype.setProperties = function setProperties (values, opt_silent) { for (var key in values) { this.set(key, values[key], opt_silent); } }; /** * Unsets a property. * @param {string} key Key name. * @param {boolean=} opt_silent Unset without triggering an event. * @api */ BaseObject.prototype.unset = function unset (key, opt_silent) { if (key in this.values_) { var oldValue = this.values_[key]; delete this.values_[key]; if (!opt_silent) { this.notify(key, oldValue); } } }; return BaseObject; }(Observable)); /** * @type {Object<string, string>} */ var changeEventTypeCache = {}; /** * @param {string} key Key name. * @return {string} Change name. */ function getChangeEventType(key) { return changeEventTypeCache.hasOwnProperty(key) ? changeEventTypeCache[key] : (changeEventTypeCache[key] = 'change:' + key); } /** * @module ol/Collection */ /** * @enum {string} * @private */ var Property = { LENGTH: 'length' }; /** * @classdesc * Events emitted by {@link module:ol/Collection~Collection} instances are instances of this * type. */ var CollectionEvent = /*@__PURE__*/(function (Event) { function CollectionEvent(type, opt_element) { Event.call(this, type); /** * The element that is added to or removed from the collection. * @type {*} * @api */ this.element = opt_element; } if ( Event ) CollectionEvent.__proto__ = Event; CollectionEvent.prototype = Object.create( Event && Event.prototype ); CollectionEvent.prototype.constructor = CollectionEvent; return CollectionEvent; }(Event$1)); /** * @typedef {Object} Options * @property {boolean} [unique=false] Disallow the same item from being added to * the collection twice. */ /** * @classdesc * An expanded version of standard JS Array, adding convenience methods for * manipulation. Add and remove changes to the Collection trigger a Collection * event. Note that this does not cover changes to the objects _within_ the * Collection; they trigger events on the appropriate object, not on the * Collection as a whole. * * @fires CollectionEvent * * @template T * @api */ var Collection = /*@__PURE__*/(function (BaseObject) { function Collection(opt_array, opt_options) { BaseObject.call(this); var options = opt_options || {}; /** * @private * @type {boolean} */ this.unique_ = !!options.unique; /** * @private * @type {!Array<T>} */ this.array_ = opt_array ? opt_array : []; if (this.unique_) { for (var i = 0, ii = this.array_.length; i < ii; ++i) { this.assertUnique_(this.array_[i], i); } } this.updateLength_(); } if ( BaseObject ) Collection.__proto__ = BaseObject; Collection.prototype = Object.create( BaseObject && BaseObject.prototype ); Collection.prototype.constructor = Collection; /** * Remove all elements from the collection. * @api */ Collection.prototype.clear = function clear () { while (this.getLength() > 0) { this.pop(); } }; /** * Add elements to the collection. This pushes each item in the provided array * to the end of the collection. * @param {!Array<T>} arr Array. * @return {Collection<T>} This collection. * @api */ Collection.prototype.extend = function extend (arr) { for (var i = 0, ii = arr.length; i < ii; ++i) { this.push(arr[i]); } return this; }; /** * Iterate over each element, calling the provided callback. * @param {function(T, number, Array<T>): *} f The function to call * for every element. This function takes 3 arguments (the element, the * index and the array). The return value is ignored. * @api */ Collection.prototype.forEach = function forEach (f) { var array = this.array_; for (var i = 0, ii = array.length; i < ii; ++i) { f(array[i], i, array); } }; /** * Get a reference to the underlying Array object. Warning: if the array * is mutated, no events will be dispatched by the collection, and the * collection's "length" property won't be in sync with the actual length * of the array. * @return {!Array<T>} Array. * @api */ Collection.prototype.getArray = function getArray () { return this.array_; }; /** * Get the element at the provided index. * @param {number} index Index. * @return {T} Element. * @api */ Collection.prototype.item = function item (index) { return this.array_[index]; }; /** * Get the length of this collection. * @return {number} The length of the array. * @observable * @api */ Collection.prototype.getLength = function getLength () { return this.get(Property.LENGTH); }; /** * Insert an element at the provided index. * @param {number} index Index. * @param {T} elem Element. * @api */ Collection.prototype.insertAt = function insertAt (index, elem) { if (this.unique_) { this.assertUnique_(elem); } this.array_.splice(index, 0, elem); this.updateLength_(); this.dispatchEvent( new CollectionEvent(CollectionEventType.ADD, elem)); }; /** * Remove the last element of the collection and return it. * Return `undefined` if the collection is empty. * @return {T|undefined} Element. * @api */ Collection.prototype.pop = function pop () { return this.removeAt(this.getLength() - 1); }; /** * Insert the provided element at the end of the collection. * @param {T} elem Element. * @return {number} New length of the collection. * @api */ Collection.prototype.push = function push (elem) { if (this.unique_) { this.assertUnique_(elem); } var n = this.getLength(); this.insertAt(n, elem); return this.getLength(); }; /** * Remove the first occurrence of an element from the collection. * @param {T} elem Element. * @return {T|undefined} The removed element or undefined if none found. * @api */ Collection.prototype.remove = function remove (elem) { var arr = this.array_; for (var i = 0, ii = arr.length; i < ii; ++i) { if (arr[i] === elem) { return this.removeAt(i); } } return undefined; }; /** * Remove the element at the provided index and return it. * Return `undefined` if the collection does not contain this index. * @param {number} index Index. * @return {T|undefined} Value. * @api */ Collection.prototype.removeAt = function removeAt (index) { var prev = this.array_[index]; this.array_.splice(index, 1); this.updateLength_(); this.dispatchEvent(new CollectionEvent(CollectionEventType.REMOVE, prev)); return prev; }; /** * Set the element at the provided index. * @param {number} index Index. * @param {T} elem Element. * @api */ Collection.prototype.setAt = function setAt (index, elem) { var n = this.getLength(); if (index < n) { if (this.unique_) { this.assertUnique_(elem, index); } var prev = this.array_[index]; this.array_[index] = elem; this.dispatchEvent( new CollectionEvent(CollectionEventType.REMOVE, prev)); this.dispatchEvent( new CollectionEvent(CollectionEventType.ADD, elem)); } else { for (var j = n; j < index; ++j) { this.insertAt(j, undefined); } this.insertAt(index, elem); } }; /** * @private */ Collection.prototype.updateLength_ = function updateLength_ () { this.set(Property.LENGTH, this.array_.length); }; /** * @private * @param {T} elem Element. * @param {number=} opt_except Optional index to ignore. */ Collection.prototype.assertUnique_ = function assertUnique_ (elem, opt_except) { for (var i = 0, ii = this.array_.length; i < ii; ++i) { if (this.array_[i] === elem && i !== opt_except) { throw new AssertionError(58); } } }; return Collection; }(BaseObject)); /** * @module ol/asserts */ /** * @param {*} assertion Assertion we expected to be truthy. * @param {number} errorCode Error code. */ function assert(assertion, errorCode) { if (!assertion) { throw new AssertionError(errorCode); } } /** * @module ol/Feature */ /** * @typedef {typeof Feature|typeof import("./render/Feature.js").default} FeatureClass */ /** * @typedef {Feature|import("./render/Feature.js").default} FeatureLike */ /** * @classdesc * A vector object for geographic features with a geometry and other * attribute properties, similar to the features in vector file formats like * GeoJSON. * * Features can be styled individually with `setStyle`; otherwise they use the * style of their vector layer. * * Note that attribute properties are set as {@link module:ol/Object} properties on * the feature object, so they are observable, and have get/set accessors. * * Typically, a feature has a single geometry property. You can set the * geometry using the `setGeometry` method and get it with `getGeometry`. * It is possible to store more than one geometry on a feature using attribute * properties. By default, the geometry used for rendering is identified by * the property name `geometry`. If you want to use another geometry property * for rendering, use the `setGeometryName` method to change the attribute * property associated with the geometry for the feature. For example: * * ```js * * import Feature from 'ol/Feature'; * import Polygon from 'ol/geom/Polygon'; * import Point from 'ol/geom/Point'; * * var feature = new Feature({ * geometry: new Polygon(polyCoords), * labelPoint: new Point(labelCoords), * name: 'My Polygon' * }); * * // get the polygon geometry * var poly = feature.getGeometry(); * * // Render the feature as a point using the coordinates from labelPoint * feature.setGeometryName('labelPoint'); * * // get the point geometry * var point = feature.getGeometry(); * ``` * * @api */ var Feature = /*@__PURE__*/(function (BaseObject) { function Feature(opt_geometryOrProperties) { BaseObject.call(this); /** * @private * @type {number|string|undefined} */ this.id_ = undefined; /** * @type {string} * @private */ this.geometryName_ = 'geometry'; /** * User provided style. * @private * @type {import("./style/Style.js").StyleLike} */ this.style_ = null; /** * @private * @type {import("./style/Style.js").StyleFunction|undefined} */ this.styleFunction_ = undefined; /** * @private * @type {?import("./events.js").EventsKey} */ this.geometryChangeKey_ = null; listen( this, getChangeEventType(this.geometryName_), this.handleGeometryChanged_, this); if (opt_geometryOrProperties) { if (typeof /** @type {?} */ (opt_geometryOrProperties).getSimplifiedGeometry === 'function') { var geometry = /** @type {import("./geom/Geometry.js").default} */ (opt_geometryOrProperties); this.setGeometry(geometry); } else { /** @type {Object<string, *>} */ var properties = opt_geometryOrProperties; this.setProperties(properties); } } } if ( BaseObject ) Feature.__proto__ = BaseObject; Feature.prototype = Object.create( BaseObject && BaseObject.prototype ); Feature.prototype.constructor = Feature; /** * Clone this feature. If the original feature has a geometry it * is also cloned. The feature id is not set in the clone. * @return {Feature} The clone. * @api */ Feature.prototype.clone = function clone () { var clone = new Feature(this.getProperties()); clone.setGeometryName(this.getGeometryName()); var geometry = this.getGeometry(); if (geometry) { clone.setGeometry(geometry.clone()); } var style = this.getStyle(); if (style) { clone.setStyle(style); } return clone; }; /** * Get the feature's default geometry. A feature may have any number of named * geometries. The "default" geometry (the one that is rendered by default) is * set when calling {@link module:ol/Feature~Feature#setGeometry}. * @return {import("./geom/Geometry.js").default|undefined} The default geometry for the feature. * @api * @observable */ Feature.prototype.getGeometry = function getGeometry () { return ( /** @type {import("./geom/Geometry.js").default|undefined} */ (this.get(this.geometryName_)) ); }; /** * Get the feature identifier. This is a stable identifier for the feature and * is either set when reading data from a remote source or set explicitly by * calling {@link module:ol/Feature~Feature#setId}. * @return {number|string|undefined} Id. * @api */ Feature.prototype.getId = function getId () { return this.id_; }; /** * Get the name of the feature's default geometry. By default, the default * geometry is named `geometry`. * @return {string} Get the property name associated with the default geometry * for this feature. * @api */ Feature.prototype.getGeometryName = function getGeometryName () { return this.geometryName_; }; /** * Get the feature's style. Will return what was provided to the * {@link module:ol/Feature~Feature#setStyle} method. * @return {import("./style/Style.js").StyleLike} The feature style. * @api */ Feature.prototype.getStyle = function getStyle () { return this.style_; }; /** * Get the feature's style function. * @return {import("./style/Style.js").StyleFunction|undefined} Return a function * representing the current style of this feature. * @api */ Feature.prototype.getStyleFunction = function getStyleFunction () { return this.styleFunction_; }; /** * @private */ Feature.prototype.handleGeometryChange_ = function handleGeometryChange_ () { this.changed(); }; /** * @private */ Feature.prototype.handleGeometryChanged_ = function handleGeometryChanged_ () { if (this.geometryChangeKey_) { unlistenByKey(this.geometryChangeKey_); this.geometryChangeKey_ = null; } var geometry = this.getGeometry(); if (geometry) { this.geometryChangeKey_ = listen(geometry, EventType.CHANGE, this.handleGeometryChange_, this); } this.changed(); }; /** * Set the default geometry for the feature. This will update the property * with the name returned by {@link module:ol/Feature~Feature#getGeometryName}. * @param {import("./geom/Geometry.js").default|undefined} geometry The new geometry. * @api * @observable */ Feature.prototype.setGeometry = function setGeometry (geometry) { this.set(this.geometryName_, geometry); }; /** * Set the style for the feature. This can be a single style object, an array * of styles, or a function that takes a resolution and returns an array of * styles. If it is `null` the feature has no style (a `null` style). * @param {import("./style/Style.js").StyleLike} style Style for this feature. * @api * @fires module:ol/events/Event~Event#event:change */ Feature.prototype.setStyle = function setStyle (style) { this.style_ = style; this.styleFunction_ = !style ? undefined : createStyleFunction(style); this.changed(); }; /** * Set the feature id. The feature id is considered stable and may be used when * requesting features or comparing identifiers returned from a remote source. * The feature id can be used with the * {@link module:ol/source/Vector~VectorSource#getFeatureById} method. * @param {number|string|undefined} id The feature id. * @api * @fires module:ol/events/Event~Event#event:change */ Feature.prototype.setId = function setId (id) { this.id_ = id; this.changed(); }; /** * Set the property name to be used when getting the feature's default geometry. * When calling {@link module:ol/Feature~Feature#getGeometry}, the value of the property with * this name will be returned. * @param {string} name The property name of the default geometry. * @api */ Feature.prototype.setGeometryName = function setGeometryName (name) { unlisten( this, getChangeEventType(this.geometryName_), this.handleGeometryChanged_, this); this.geometryName_ = name; listen( this, getChangeEventType(this.geometryName_), this.handleGeometryChanged_, this); this.handleGeometryChanged_(); }; return Feature; }(BaseObject)); /** * Convert the provided object into a feature style function. Functions passed * through unchanged. Arrays of Style or single style objects wrapped * in a new feature style function. * @param {!import("./style/Style.js").StyleFunction|!Array<import("./style/Style.js").default>|!import("./style/Style.js").default} obj * A featu