ol-plot-enhanced
Version:
ol plot enhanced
1,711 lines (1,514 loc) • 1.36 MB
JavaScript
/*!
* 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