diff --git a/src/component/draw-interaction/interaction.vue b/src/component/draw-interaction/interaction.vue
index 08938859..8069ebd2 100644
--- a/src/component/draw-interaction/interaction.vue
+++ b/src/component/draw-interaction/interaction.vue
@@ -1,6 +1,8 @@
diff --git a/src/component/vector-source/source.vue b/src/component/vector-source/source.vue
index c346e8b3..6cd6198b 100644
--- a/src/component/vector-source/source.vue
+++ b/src/component/vector-source/source.vue
@@ -90,8 +90,13 @@
loadingStrategy () {
return this.strategyFactory()
},
+ dataFormatIdent () {
+ if (!this.olObjIdent) return
+
+ return this.makeIdent(this.olObjIdent, 'data_format')
+ },
dataFormat () {
- return this.formatFactory()
+ return this.instanceFactoryCall(this.dataFormatIdent, ::this.formatFactory)
},
},
methods: {
diff --git a/src/mixin/features-container.js b/src/mixin/features-container.js
index 66a3f073..72f33ba7 100644
--- a/src/mixin/features-container.js
+++ b/src/mixin/features-container.js
@@ -8,10 +8,11 @@ import { instanceOf } from '../util/assert'
import { forEach, isPlainObject } from '../util/minilo'
import projTransforms from './proj-transforms'
import rxSubs from './rx-subs'
+import identMap from './ident-map'
import { observableFromOlEvent } from '../rx-ext'
export default {
- mixins: [rxSubs, projTransforms],
+ mixins: [identMap, rxSubs, projTransforms],
computed: {
featureIds () {
if (!this.rev) return []
@@ -28,6 +29,11 @@ export default {
return this.getFeatures().map(::this.writeFeatureInDataProj)
},
+ featuresCollectionIdent () {
+ if (!this.olObjIdent) return
+
+ return this.makeIdent(this.olObjIdent, 'features_collection')
+ },
},
methods: {
/**
@@ -116,11 +122,7 @@ export default {
},
},
created () {
- /**
- * @type {Collection>}
- * @private
- */
- this._featuresCollection = new Collection()
+ this._featuresCollection = this.instanceFactoryCall(this.featuresCollectionIdent, () => new Collection())
this._featureSubs = {}
this::defineServices()
diff --git a/src/mixin/ident-map.js b/src/mixin/ident-map.js
index 91cfcb89..a864d89b 100644
--- a/src/mixin/ident-map.js
+++ b/src/mixin/ident-map.js
@@ -1,13 +1,11 @@
import Vue from 'vue'
import IdentityMap from '../util/identity-map'
-import { identity } from '../util/minilo'
+import { identity, stubObject, keys } from '../util/minilo'
-// todo uncomment when IE 11 will die
-// const IDENTITY_MAP_PROP = Symbol('identityMap')
-const IDENTITY_MAP_PROP = 'identityMap'
+const INSTANCES_POOL = 'instances'
export default {
- IDENTITY_MAP_PROP,
+ INSTANCES_POOL,
props: {
/**
* Unique key for saving to identity map
@@ -16,6 +14,32 @@ export default {
*/
ident: [String, Number],
},
+ data () {
+ return {
+ idents: stubObject(),
+ }
+ },
+ computed: {
+ selfIdent () {
+ return this.makeSelfIdent()
+ },
+ },
+ watch: {
+ ident (value, prev) {
+ if (prev && this.$identityMap.has(prev)) {
+ this.$identityMap.unset(prev)
+ }
+ if (value && !this.$identityMap.has(value)) {
+ this.$identityMap.set(value)
+ }
+ },
+ },
+ beforeCreate () {
+ initIdentityMap()
+ },
+ destroyed () {
+ this.unsetInstances()
+ },
methods: {
/**
* @param parts
@@ -34,33 +58,65 @@ export default {
makeIdent (...parts) {
return parts.filter(identity).join('.')
},
- },
- created () {
- this::initIdentityMap()
- },
- watch: {
- ident (value, prev) {
- if (prev && this.$identityMap.has(prev)) {
- this.$identityMap.unset(prev)
+ /**
+ * Caches or reuse factory result in the identity map
+ * and returns result.
+ *
+ * @param {string|undefined} ident
+ * @param {function} factory
+ * @returns {*}
+ */
+ instanceFactoryCall (ident, factory) {
+ if (ident && this.$identityMap.has(ident, INSTANCES_POOL)) {
+ return this.$identityMap.get(ident, INSTANCES_POOL)
}
- if (value && !this.$identityMap.has(value)) {
- this.$identityMap.set(value)
+
+ const val = factory()
+
+ if (ident) {
+ this.idents[ident] = true
+ this.$identityMap.set(ident, val, INSTANCES_POOL)
}
+
+ return val
+ },
+ /**
+ * @param {string|undefined} ident
+ * @returns {*}
+ */
+ getInstance (ident) {
+ if (!ident) return
+
+ return this.$identityMap.get(ident, INSTANCES_POOL)
+ },
+ /**
+ * Unsets all self indets
+ * @return {void}
+ */
+ unsetInstances () {
+ keys(this.idents).forEach(ident => this.$identityMap.unset(ident, INSTANCES_POOL))
},
},
}
-/**
- * @private
- */
function initIdentityMap () {
- if (!this[IDENTITY_MAP_PROP]) {
- Vue[IDENTITY_MAP_PROP] = Vue.prototype[IDENTITY_MAP_PROP] = new IdentityMap()
+ const imap = new IdentityMap()
+
+ if (!('$identityMap' in Vue)) {
+ Object.defineProperties(Vue, {
+ $identityMap: {
+ enumerable: true,
+ get: () => imap,
+ },
+ })
+ }
+
+ if (!('$identityMap' in Vue.prototype)) {
+ Object.defineProperties(Vue.prototype, {
+ $identityMap: {
+ enumerable: true,
+ get: () => imap,
+ },
+ })
}
- Object.defineProperties(this, {
- $identityMap: {
- enumerable: true,
- get: () => this[IDENTITY_MAP_PROP],
- },
- })
}
diff --git a/src/mixin/interactions-container.js b/src/mixin/interactions-container.js
index fb214b4f..66bd7e11 100644
--- a/src/mixin/interactions-container.js
+++ b/src/mixin/interactions-container.js
@@ -5,16 +5,22 @@ import { merge as mergeObs } from 'rxjs/observable'
import { getInteractionId, getInteractionPriority, initializeInteraction } from '../ol-ext'
import { instanceOf } from '../util/assert'
import rxSubs from './rx-subs'
+import identMap from './ident-map'
import { observableFromOlEvent } from '../rx-ext'
export default {
- mixins: [rxSubs],
+ mixins: [identMap, rxSubs],
computed: {
interactionIds () {
if (!this.rev) return []
return this.getInteractions().map(getInteractionId)
},
+ interactionsCollectionIdent () {
+ if (!this.olObjIdent) return
+
+ return this.makeIdent(this.olObjIdent, 'interactions_collection')
+ },
},
methods: {
/**
@@ -103,11 +109,7 @@ export default {
},
},
created () {
- /**
- * @type {Collection>}
- * @private
- */
- this._interactionsCollection = new Collection()
+ this._interactionsCollection = this.instanceFactoryCall(this.interactionsCollectionIdent, () => new Collection())
this::defineServices()
this::subscribeToCollectionEvents()
diff --git a/src/mixin/layers-container.js b/src/mixin/layers-container.js
index fb5d8864..b44babab 100644
--- a/src/mixin/layers-container.js
+++ b/src/mixin/layers-container.js
@@ -6,15 +6,21 @@ import { getLayerId, initializeLayer } from '../ol-ext'
import { observableFromOlEvent } from '../rx-ext'
import { instanceOf } from '../util/assert'
import rxSubs from './rx-subs'
+import identMap from './ident-map'
export default {
- mixins: [rxSubs],
+ mixins: [identMap, rxSubs],
computed: {
layerIds () {
if (!this.rev) return []
return this.getLayers().map(getLayerId)
},
+ layersCollectionIdent () {
+ if (!this.olObjIdent) return
+
+ return this.makeIdent(this.olObjIdent, 'layers_collection')
+ },
},
methods: {
/**
@@ -80,11 +86,7 @@ export default {
},
},
created () {
- /**
- * @type {Collection}
- * @private
- */
- this._layersCollection = new Collection()
+ this._layersCollection = this.instanceFactoryCall(this.layersCollectionIdent, () => new Collection())
this::defineServices()
this::subscribeToCollectionEvents()
diff --git a/src/mixin/ol-cmp.js b/src/mixin/ol-cmp.js
index b903f4bc..6ec39fb3 100644
--- a/src/mixin/ol-cmp.js
+++ b/src/mixin/ol-cmp.js
@@ -9,7 +9,6 @@ import rxSubs from './rx-subs'
import services from './services'
const VM_PROP = 'vm'
-const INSTANCE_PROMISE_POOL = 'instance_promise'
/**
* Basic ol component mixin.
@@ -17,7 +16,6 @@ const INSTANCE_PROMISE_POOL = 'instance_promise'
*/
export default {
VM_PROP,
- INSTANCE_PROMISE_POOL,
mixins: [identMap, rxSubs, services],
props: {
id: {
@@ -40,6 +38,9 @@ export default {
vmName () {
return [this.cmpName, this.id].filter(identity).join(' ')
},
+ olObjIdent () {
+ return this.selfIdent
+ },
},
methods: {
/**
@@ -52,20 +53,7 @@ export default {
* @protected
*/
async init () {
- let createPromise
-
- const ident = this.makeSelfIdent()
- if (ident && this.$identityMap.has(ident, INSTANCE_PROMISE_POOL)) {
- createPromise = this.$identityMap.get(ident, INSTANCE_PROMISE_POOL)
- } else {
- createPromise = this.createOlObject()
-
- if (ident) {
- this.$identityMap.set(ident, createPromise, INSTANCE_PROMISE_POOL)
- }
- }
-
- this._olObject = await createPromise
+ this._olObject = await this.instanceFactoryCall(this.olObjIdent, ::this.createOlObject)
this._olObject[VM_PROP] || (this._olObject[VM_PROP] = [])
if (!this._olObject[VM_PROP].includes(this)) { // for loaded from IdentityMap
@@ -87,10 +75,8 @@ export default {
* @protected
*/
deinit () {
- const ident = this.makeSelfIdent()
- if (ident) {
- this.$identityMap.unset(ident, INSTANCE_PROMISE_POOL)
- }
+ this.unsetInstances()
+
if (this._olObject) {
this._olObject[VM_PROP] = this._olObject[VM_PROP].filter(vm => vm !== this)
this._olObject = undefined
diff --git a/src/mixin/overlays-container.js b/src/mixin/overlays-container.js
index 8ab6e100..ace20e48 100644
--- a/src/mixin/overlays-container.js
+++ b/src/mixin/overlays-container.js
@@ -6,15 +6,21 @@ import { getOverlayId, initializeOverlay } from '../ol-ext'
import { observableFromOlEvent } from '../rx-ext'
import { instanceOf } from '../util/assert'
import rxSubs from './rx-subs'
+import identMap from './ident-map'
export default {
- mixins: [rxSubs],
+ mixins: [identMap, rxSubs],
computed: {
overlayIds () {
if (!this.rev) return []
return this.getOverlays().map(getOverlayId)
},
+ overlaysCollectionIdent () {
+ if (!this.olObjIdent) return
+
+ return this.makeIdent(this.olObjIdent, 'overlays_collection')
+ },
},
methods: {
/**
@@ -80,11 +86,7 @@ export default {
},
},
created () {
- /**
- * @type {Collection}
- * @private
- */
- this._overlaysCollection = new Collection()
+ this._overlaysCollection = this.instanceFactoryCall(this.overlaysCollectionIdent, () => new Collection())
this::defineServices()
this::subscribeToCollectionEvents()
diff --git a/src/mixin/tile-source.js b/src/mixin/tile-source.js
index 63f820c7..e2e56000 100644
--- a/src/mixin/tile-source.js
+++ b/src/mixin/tile-source.js
@@ -99,6 +99,11 @@ export default {
return url
},
+ tileGridIdent () {
+ if (!this.olObjIdent) return
+
+ return this.makeIdent(this.olObjIdent, 'tile_grid')
+ },
},
methods: {
createTileGrid () {
@@ -118,7 +123,7 @@ export default {
* @type {module:ol/Tile~UrlFunction}
* @protected
*/
- this._tileGrid = this.createTileGrid()
+ this._tileGrid = this.instanceFactoryCall(this.tileGridIdent, ::this.createTileGrid)
return this::source.methods.init()
},
diff --git a/src/util/assert.js b/src/util/assert.js
index 5d4816b2..95b9edb9 100644
--- a/src/util/assert.js
+++ b/src/util/assert.js
@@ -34,19 +34,21 @@ export function ok (value, message) {
/**
* @param {*} value
+ * @param {string|undefined} [msg]
* @throws {AssertionError}
*/
-export function numeric (value) {
- assert(isNumeric(value), 'value is a number')
+export function numeric (value, msg) {
+ assert(isNumeric(value), msg || 'value is a number')
}
/**
* @param {*} value
* @param {Function} Ctor
+ * @param {string|undefined} [msg]
* @throws {AssertionError}
*/
-export function instanceOf (value, Ctor) {
- assert(value instanceof Ctor, `value is an instance of ${Ctor.name}`)
+export function instanceOf (value, Ctor, msg) {
+ assert(value instanceof Ctor, msg || `value is an instance of ${Ctor.name}`)
}
export function hasOlObject (vm) {
diff --git a/src/util/identity-map.js b/src/util/identity-map.js
index 1e829037..f83759ca 100644
--- a/src/util/identity-map.js
+++ b/src/util/identity-map.js
@@ -2,14 +2,14 @@
* Simple Identity map with refs count
*/
export default class IdentityMap {
- pools = Object.create(null)
+ _pools = Object.create(null)
/**
* @param {string} pool
* @private
*/
_preparePool (pool) {
- this.pools[pool] || (this.pools[pool] = Object.create(null))
+ this._pools[pool] || (this._pools[pool] = Object.create(null))
}
/**
@@ -22,7 +22,7 @@ export default class IdentityMap {
this._preparePool(pool)
- this.pools[pool][id] = {
+ this._pools[pool][id] = {
value,
refs: 1,
}
@@ -35,11 +35,11 @@ export default class IdentityMap {
get (id, pool = 'default') {
this._preparePool(pool)
- let rec = this.pools[pool][id]
+ let rec = this._pools[pool][id]
if (!rec || rec.value == null) return
rec.refs++
- this.pools[pool][id] = rec
+ this._pools[pool][id] = rec
return rec.value
}
@@ -51,14 +51,12 @@ export default class IdentityMap {
unset (id, pool = 'default') {
this._preparePool(pool)
- let rec = this.pools[pool][id]
+ let rec = this._pools[pool][id]
if (!rec || rec.value == null) return
rec.refs--
if (rec.refs === 0) {
- delete this.pools[pool][id]
- } else {
- this.pools[pool][id] = rec
+ delete this._pools[pool][id]
}
}
@@ -70,7 +68,7 @@ export default class IdentityMap {
has (id, pool = 'default') {
this._preparePool(pool)
- return !!this.pools[pool][id]
+ return !!this._pools[pool][id]
}
/**
@@ -80,7 +78,7 @@ export default class IdentityMap {
ids (pool = 'default') {
this._preparePool(pool)
- return Object.keys(this.pools[pool])
+ return Object.keys(this._pools[pool])
}
/**
@@ -91,6 +89,6 @@ export default class IdentityMap {
refs (id, pool = 'default') {
this._preparePool(pool)
- return this.has(id, pool) ? this.pools[pool][id].refs : undefined
+ return this.has(id, pool) ? this._pools[pool][id].refs : undefined
}
}
diff --git a/src/util/minilo.js b/src/util/minilo.js
index 175ec92c..52adcbbe 100644
--- a/src/util/minilo.js
+++ b/src/util/minilo.js
@@ -29,6 +29,10 @@ export function stubArray () {
return []
}
+export function stubObject () {
+ return Object.create(null)
+}
+
export function identity (value) {
return value
}
@@ -185,6 +189,14 @@ export function isNotEmpty (value) {
return !isEmpty(value)
}
+export function keys (object) {
+ return Object.keys(object)
+}
+
+export function values (object) {
+ return Object.values(object)
+}
+
export function forEach (collection, iteratee) {
let keys = Object.keys(collection)
for (let i = 0, l = keys.length; i < l; i++) {
diff --git a/test/app.vue b/test/app.vue
index 51b75a62..6d123a0f 100644
--- a/test/app.vue
+++ b/test/app.vue
@@ -6,9 +6,11 @@
Selected:
{{ selectedFeatureIds }}
+
-
+
@@ -30,18 +32,19 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -62,36 +65,25 @@
resolution: 39135.75848201024,
center: [100, 10],
rotation: 0,
+ mapVisible: true,
countriesUrl: 'https://openlayers.org/en/latest/examples/data/geojson/countries.geojson',
countries: [],
featureId: undefined,
features: [],
selectedFeatures: [],
- drawFeatures: [
- {
- type: 'Feature',
- id: '213456789',
- properties: {},
- geometry: {
- type: 'Polygon',
- coordinates: [[
- [0, 0],
- [20, 0],
- [20, 20],
- [0, 20],
- [0, 0],
- ]],
- },
- },
- ],
+ drawFeatures: [],
controls: true,
interactions: true,
- places: range(0, 100).map(i => ({
+ points: range(0, 100).map(i => ({
+ type: 'Feature',
id: 'random-' + i,
- geo: [
- random(0, 50),
- random(0, 50),
- ],
+ geometry: {
+ type: 'Point',
+ coordinates: [
+ random(0, 50),
+ random(0, 50),
+ ],
+ },
})),
}
},
@@ -132,26 +124,11 @@
return [style]
}
},
- getPlaceFeatures () {
- const sourceVm = this.$refs.placesSource
- sourceVm.$source.clear()
-
- const features = this.places.map(place => {
- const geometry = new Point(place.geo)
- geometry.transform('EPSG:4326', 'EPSG:3857')
-
- let feature = new Feature({ geometry })
- feature.setProperties(place)
- feature.setId(place.id)
-
- return feature
- })
-
- sourceVm.$source.addFeatures(features)
+ toggleMap () {
+ this.mapVisible = !this.mapVisible
+ this.drawFeatures = []
},
},
- mounted () {
- },
}
diff --git a/test/main.js b/test/main.js
index f92e3f07..029f3be1 100644
--- a/test/main.js
+++ b/test/main.js
@@ -1,6 +1,6 @@
import '@babel/polyfill'
import Vue from 'vue'
-import VueLayers from '@'
+import VueLayers from '../src'
import App from './app.vue'
Vue.performance = true
@@ -10,6 +10,7 @@ Vue.use(VueLayers, {
// dataProjection: 'EPSG:4326',
})
console.log(process.env.NODE_ENV)
+console.dir(Vue)
console.dir(VueLayers)
/* eslint-disable no-new */
new Vue({