@openglobus/og 0.13.7 → 0.13.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/css/og.css +388 -129
- package/dist/@openglobus/og.css +1 -1
- package/dist/@openglobus/og.esm.js +2 -2
- package/dist/@openglobus/og.esm.js.map +1 -1
- package/dist/@openglobus/og.umd.js +2 -2
- package/dist/@openglobus/og.umd.js.map +1 -1
- package/package.json +20 -19
- package/src/og/Globe.js +15 -16
- package/src/og/Object3d.js +417 -0
- package/src/og/arial.js +1705 -1703
- package/src/og/camera/Camera.js +640 -640
- package/src/og/control/EarthCoordinates.js +1 -1
- package/src/og/control/GeoImageDragControl.js +102 -75
- package/src/og/control/LayerAnimation.js +383 -0
- package/src/og/control/LayerSwitcher.js +506 -159
- package/src/og/control/Lighting.js +27 -27
- package/src/og/control/MouseNavigation.js +460 -460
- package/src/og/control/RulerSwitcher.js +69 -0
- package/src/og/control/Sun.js +170 -170
- package/src/og/control/UIhelpers.js +146 -0
- package/src/og/control/ZoomControl.js +0 -2
- package/src/og/control/index.js +5 -1
- package/src/og/control/ruler/Ruler.js +43 -0
- package/src/og/control/ruler/RulerScene.js +374 -0
- package/src/og/control/visibleExtent/Segment.js +3 -5
- package/src/og/ellipsoid/Ellipsoid.js +19 -0
- package/src/og/ellipsoid/wgs84.js +1 -1
- package/src/og/entity/Entity.js +1 -1
- package/src/og/entity/GeoObject.js +1 -1
- package/src/og/entity/LabelHandler.js +6 -2
- package/src/og/entity/LabelWorker.js +38 -53
- package/src/og/layer/BaseGeoImage.js +347 -312
- package/src/og/layer/CanvasTiles.js +312 -290
- package/src/og/layer/GeoImage.js +222 -214
- package/src/og/layer/GeoVideo.js +291 -291
- package/src/og/layer/Layer.js +94 -70
- package/src/og/layer/Material.js +109 -109
- package/src/og/layer/Vector.js +81 -14
- package/src/og/layer/XYZ.js +23 -11
- package/src/og/light/LightSource.js +364 -363
- package/src/og/math/Vec3.js +1 -1
- package/src/og/math.js +6 -6
- package/src/og/quadTree/Node.js +8 -6
- package/src/og/renderer/Renderer.js +2 -3
- package/src/og/res/images.js +0 -2
- package/src/og/scene/Planet.js +106 -44
- package/src/og/segment/Segment.js +34 -64
- package/src/og/segment/Slice.js +1 -1
- package/src/og/shaders/drawnode.js +1 -1
- package/src/og/shaders/label.js +30 -42
- package/src/og/terrain/GlobusTerrain.js +31 -20
- package/src/og/terrain/MapboxTerrain.js +1 -1
- package/src/og/utils/BaseWorker.js +46 -0
- package/src/og/utils/FontAtlas.js +1 -2
- package/src/og/utils/GeoImageCreator.js +164 -161
- package/src/og/utils/Loader.js +187 -153
- package/src/og/utils/NormalMapCreator.js +403 -412
- package/src/og/utils/PlainSegmentWorker.js +29 -55
- package/src/og/utils/TerrainWorker.js +572 -589
- package/src/og/utils/VectorTileCreator.js +1 -1
- package/src/og/utils/functionComposition.js +13 -0
- package/src/og/webgl/Handler.js +42 -41
- package/src/og/webgl/ProgramController.js +143 -143
- package/types/Object3d.d.ts +22 -0
- package/types/arial.d.ts +1 -0
- package/types/camera/PlanetCamera.d.ts +4 -0
- package/types/control/GeoImageDragControl.d.ts +2 -0
- package/types/control/LayerAnimation.d.ts +73 -0
- package/types/control/LayerSwitcher.d.ts +55 -11
- package/types/control/MouseNavigation.d.ts +1 -0
- package/types/control/MouseWheelZoomControl.d.ts +1 -0
- package/types/control/Sun.d.ts +2 -1
- package/types/control/TouchNavigation.d.ts +1 -0
- package/types/control/UIhelpers.d.ts +13 -0
- package/types/control/index.d.ts +3 -1
- package/types/control/ruler/Ruler.d.ts +13 -0
- package/types/control/ruler/RulerScene.d.ts +48 -0
- package/types/ellipsoid/Ellipsoid.d.ts +8 -0
- package/types/entity/LabelHandler.d.ts +2 -0
- package/types/entity/LabelWorker.d.ts +5 -7
- package/types/layer/BaseGeoImage.d.ts +9 -1
- package/types/layer/CanvasTiles.d.ts +5 -1
- package/types/layer/GeoImage.d.ts +1 -0
- package/types/layer/GeoTexture2d.d.ts +1 -0
- package/types/layer/Layer.d.ts +28 -32
- package/types/layer/Vector.d.ts +9 -0
- package/types/layer/WMS.d.ts +1 -0
- package/types/layer/XYZ.d.ts +8 -5
- package/types/math.d.ts +2 -2
- package/types/quadTree/EntityCollectionNode.d.ts +7 -0
- package/types/quadTree/Node.d.ts +1 -2
- package/types/renderer/Renderer.d.ts +1 -1
- package/types/renderer/RendererEvents.d.ts +16 -0
- package/types/res/images.d.ts +0 -1
- package/types/scene/Planet.d.ts +21 -6
- package/types/segment/SegmentLonLat.d.ts +2 -0
- package/types/terrain/BilTerrain.d.ts +6 -0
- package/types/terrain/GlobusTerrain.d.ts +7 -0
- package/types/terrain/MapboxTerrain.d.ts +8 -0
- package/types/utils/BaseWorker.d.ts +14 -0
- package/types/utils/Loader.d.ts +4 -1
- package/types/utils/PlainSegmentWorker.d.ts +4 -6
- package/types/utils/TerrainWorker.d.ts +4 -6
- package/types/utils/functionComposition.d.ts +5 -0
- package/types/webgl/Handler.d.ts +4 -1
|
@@ -1,159 +1,506 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module og/control/LayerSwitcher
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
"use strict";
|
|
6
|
-
|
|
7
|
-
import { Control } from "./Control.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module og/control/LayerSwitcher
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
import { Control } from "./Control.js";
|
|
8
|
+
import { elementFactory, appendChildren, toggleText, enableElmovement } from "./UIhelpers.js";
|
|
9
|
+
import { compose } from "../utils/functionComposition.js"
|
|
10
|
+
/**
|
|
11
|
+
* Advanced :) layer switcher, includes base layers, overlays, geo images etc. groups.
|
|
12
|
+
* Double click for zoom, drag-and-drop to change zIndex
|
|
13
|
+
* @class
|
|
14
|
+
* @extends {Control}
|
|
15
|
+
* @param {Object} [options] - Control options.
|
|
16
|
+
*/
|
|
17
|
+
class LayerSwitcher extends Control {
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
super({
|
|
20
|
+
name: "LayerSwitcher",
|
|
21
|
+
...options
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
this._id = LayerSwitcher.numSwitches++;
|
|
25
|
+
this.switcherDependent = options.switcherDependent
|
|
26
|
+
this.expandedSections = options.expandedSections
|
|
27
|
+
this.switcherInMenu = options.switcherInMenu // none (default)
|
|
28
|
+
this.docListener = options.docListener
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static get numSwitches() {
|
|
32
|
+
if (!this._counter && this._counter !== 0) {
|
|
33
|
+
this._counter = 0;
|
|
34
|
+
}
|
|
35
|
+
return this._counter;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static set numSwitches(n) {
|
|
39
|
+
this._counter = n;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
oninit() {
|
|
43
|
+
this.setupSwitcher()
|
|
44
|
+
this.planet.events.on("layeradd", this.addNewLayer, this)
|
|
45
|
+
this.planet.events.on("layerremove", this.removeLayer, this)
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setupSwitcher () {
|
|
50
|
+
const myData = this.getRecords(this.planet)
|
|
51
|
+
const { $mainContainer } = this.buildBasicDOM()
|
|
52
|
+
this.buildRecords(myData, $mainContainer, 0)
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onactivate() {
|
|
57
|
+
this.setupSwitcher()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
ondeactivate() {
|
|
61
|
+
const $menuBtn = document.getElementById('og-layer-switcher-menu-btn')
|
|
62
|
+
const $dialog = document.getElementById('og-layer-switcher-dialog')
|
|
63
|
+
$menuBtn.remove()
|
|
64
|
+
$dialog.remove()
|
|
65
|
+
document.removeEventListener('click', (e) => this.docListener(e))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// BASIC DATA COLLECTION-PREPARATION FUNCTIONS
|
|
69
|
+
planetDataBasic() {
|
|
70
|
+
|
|
71
|
+
const collectTerrains = (planet) => {
|
|
72
|
+
return [...planet._terrainPool]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const collectLayers = (planet) => {
|
|
76
|
+
return planet.getLayers()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const pickBaseLayers = (layers) => {
|
|
80
|
+
return layers.filter(x => x.isBaseLayer())
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const pickOverlays = (layers) => {
|
|
84
|
+
return layers.filter(x => !x.isBaseLayer())
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const classifyObject = (object) => {
|
|
88
|
+
let r = object.isBaseLayer()
|
|
89
|
+
if (r === true || r === false) {
|
|
90
|
+
return r === true ? 'BaseLayers' : 'Overlays'
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return 'Terrain Providers'
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const sortByZIndex = (layers) => {
|
|
98
|
+
return layers.sort((a, b) => (a.getZIndex() < b.getZIndex()) ? 1 : -1)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const serializeZIndices = (layers) => {
|
|
102
|
+
layers.forEach((el, i) => el.setZIndex(10000 - i * 100))
|
|
103
|
+
return layers
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const normalizeOverlay = (overlay) => {
|
|
107
|
+
overlay.data = overlay._entities || null
|
|
108
|
+
return overlay
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
collectTerrains, collectLayers, pickBaseLayers, pickOverlays,
|
|
113
|
+
classifyObject, sortByZIndex, serializeZIndices, normalizeOverlay
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// OUTPOUT TERRAINS, BASELAYERS, OVERLAYS
|
|
118
|
+
planetDataReturn(planet) {
|
|
119
|
+
|
|
120
|
+
const { collectTerrains, collectLayers, pickBaseLayers, pickOverlays,
|
|
121
|
+
sortByZIndex, serializeZIndices, normalizeOverlay } = this.planetDataBasic()
|
|
122
|
+
|
|
123
|
+
const terrains = collectTerrains(planet)
|
|
124
|
+
|
|
125
|
+
const baseLayers = compose(planet)
|
|
126
|
+
.run(collectLayers)
|
|
127
|
+
.run(pickBaseLayers)
|
|
128
|
+
.end()
|
|
129
|
+
|
|
130
|
+
const overlays = compose(planet)
|
|
131
|
+
.run(collectLayers)
|
|
132
|
+
.run(pickOverlays)
|
|
133
|
+
.run(sortByZIndex)
|
|
134
|
+
.run(serializeZIndices)
|
|
135
|
+
.runForEach(normalizeOverlay)
|
|
136
|
+
.end()
|
|
137
|
+
|
|
138
|
+
return { terrains, baseLayers, overlays }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
dialogSectionStructure(name, input, data) {
|
|
142
|
+
const section = {}
|
|
143
|
+
section.name = name
|
|
144
|
+
section.input = input
|
|
145
|
+
section.data = data
|
|
146
|
+
return section
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
recordsStructure(terrains, baseLayers, overlays) {
|
|
150
|
+
const myData = {
|
|
151
|
+
data: [
|
|
152
|
+
this.dialogSectionStructure('Terrain Providers', 'radio', terrains),
|
|
153
|
+
this.dialogSectionStructure('Base Layers', 'radio', baseLayers),
|
|
154
|
+
this.dialogSectionStructure('Overlays', 'checkbox', overlays),
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
// console.log(myData) // enable this to have a visual representation of the dialog structure
|
|
158
|
+
return myData
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
getRecords(planet) {
|
|
162
|
+
const { terrains, baseLayers, overlays } = this.planetDataReturn(planet)
|
|
163
|
+
const records = this.recordsStructure(terrains, baseLayers, overlays)
|
|
164
|
+
return records
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
addNewLayer(layer) {
|
|
168
|
+
// Put the data(layer) to the appropriate recordsStructure section and run the build function
|
|
169
|
+
const $dialog = document.getElementById('og-layer-switcher-dialog')
|
|
170
|
+
if($dialog){
|
|
171
|
+
const { classifyObject } = this.planetDataBasic()
|
|
172
|
+
const targets = [...document.body.querySelectorAll('.og-layer-switcher-record.og-depth-0 > details')]
|
|
173
|
+
const type = classifyObject(layer)
|
|
174
|
+
const object = this.recordsStructure().data.filter(x => x.name == type)
|
|
175
|
+
const index = this.recordsStructure().data.findIndex(x => x.name == type)
|
|
176
|
+
object[0].data = [layer]
|
|
177
|
+
this.buildRecords(object[0], targets[index], 1, true)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
removeLayer(layer) {
|
|
182
|
+
// TODO...Haven't tested it yet
|
|
183
|
+
let id = layer.getID()
|
|
184
|
+
let el = document.body.querySelector('#' + id + ".og-layer-switcher-record.og-depth-1")
|
|
185
|
+
el.remove()
|
|
186
|
+
|
|
187
|
+
if (layer.displayInLayerSwitcher) { // check necessary, or else error with layers not in switcher - e.g rulerScene layers.
|
|
188
|
+
layer._removeCallback();
|
|
189
|
+
layer._removeCallback = null
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
getUserPrefs() {
|
|
194
|
+
const switcherDependency = this.switcherDependent == undefined ? true : this.switcherDependent
|
|
195
|
+
const sectionsOpening = this.expandedSections == undefined ? true : this.expandedSections
|
|
196
|
+
const btnInMenu = this.switcherInMenu == undefined ? true : this.switcherInMenu
|
|
197
|
+
|
|
198
|
+
return { switcherDependency, sectionsOpening, btnInMenu }
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
buildBasicDOM() {
|
|
202
|
+
|
|
203
|
+
const { switcherDependency, sectionsOpening, btnInMenu } = this.getUserPrefs()
|
|
204
|
+
|
|
205
|
+
// Basic DOM creation
|
|
206
|
+
const $menuBtn = elementFactory('div', { id: 'og-layer-switcher-menu-btn', class: 'og-menu-btn og-OFF' },
|
|
207
|
+
elementFactory('div', { id: 'og-layer-switcher-menu-icon', class: 'og-icon-holder' }))
|
|
208
|
+
const $dialog = elementFactory('div', { class: 'og-layer-switcher-dialog og-dialog og-not-visible', id: 'og-layer-switcher-dialog' })
|
|
209
|
+
const $header = elementFactory('div', { class: 'og-layer-switcher-dialog-header' })
|
|
210
|
+
const $header_close = elementFactory('div', { id: 'og-layer-switcher-dialog-close-btn', class: 'og-dialog-header-btn og-OFF' },
|
|
211
|
+
elementFactory('div', { class: 'og-icon-holder' }))
|
|
212
|
+
const $headerMinMax = elementFactory('div', { id: 'og-layer-switcher-dialog-minMax-btn', class: 'og-dialog-header-btn og-OFF' },
|
|
213
|
+
elementFactory('div', { class: 'og-icon-holder' }))
|
|
214
|
+
const $headerTitle = elementFactory('span', { class: 'og-dialog-header-title' }, 'Layer Switcher')
|
|
215
|
+
const $headerPin = elementFactory('div', { id: 'og-layer-switcher-dialog-pin-btn', class: 'og-dialog-header-btn og-OFF' },
|
|
216
|
+
elementFactory('div', { class: 'og-icon-holder' }))
|
|
217
|
+
const $mainContainer = elementFactory('div', { class: 'og-layer-switcher-main-container' })
|
|
218
|
+
|
|
219
|
+
$headerPin.dataset.attachement = 'UNPINNED'
|
|
220
|
+
|
|
221
|
+
// Append children to parents
|
|
222
|
+
appendChildren(this.planet.renderer.div, [$menuBtn, $dialog])
|
|
223
|
+
appendChildren($dialog, [$header, $mainContainer])
|
|
224
|
+
appendChildren($header, [$header_close, $headerMinMax, $headerTitle, $headerPin])
|
|
225
|
+
|
|
226
|
+
// Behaviour according to dependency on switcher
|
|
227
|
+
if (switcherDependency == false) {
|
|
228
|
+
$menuBtn.classList.add('og-hide') // hide menu btn
|
|
229
|
+
$dialog.classList.remove('og-not-visible') // Show dialog when opening webpage
|
|
230
|
+
$headerPin.classList.add('og-not-visible') // hide the pin that attaches the dialog window
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const dialogBoxInitial = $dialog.getBoundingClientRect() // Initial position of the dialog window
|
|
234
|
+
|
|
235
|
+
// LISTENERS
|
|
236
|
+
const whereClick = (e, wrapper, menuBtn) => {
|
|
237
|
+
if (wrapper.contains(e.target)) { return 'inside' }
|
|
238
|
+
else if (menuBtn.contains(e.target)) { return 'on-btn' }
|
|
239
|
+
else { return 'outside' }
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
var whereClickHandler = null
|
|
243
|
+
whereClickHandler = (e) => { // cannot be a const otherwise cannot be created again in onactivate()
|
|
244
|
+
// Check where I clicked : in dialog, in button, elsewhere
|
|
245
|
+
let whereIclicked = $menuBtn ? whereClick(e, $dialog, $menuBtn) : null
|
|
246
|
+
|
|
247
|
+
// If I clicked elsewhere and the dialog is unpinned, then hide dialog and set menu btn to OFF
|
|
248
|
+
if (whereIclicked === 'outside' && $headerPin.dataset.attachement == 'UNPINNED') {
|
|
249
|
+
$dialog.classList.add('og-not-visible')
|
|
250
|
+
$menuBtn.classList.add('og-OFF')
|
|
251
|
+
// If Iclicked on button, toggle dialog and menu btn
|
|
252
|
+
} else if (whereIclicked === 'on-btn') {
|
|
253
|
+
$dialog.classList.toggle('og-not-visible')
|
|
254
|
+
$menuBtn.classList.toggle('og-OFF')
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this.docListener = whereClickHandler // Function holder so that it is the same during add/remove
|
|
259
|
+
|
|
260
|
+
// Document
|
|
261
|
+
document.addEventListener('click', (e) => this.docListener(e))
|
|
262
|
+
|
|
263
|
+
// Header pin - here I am using instead of CSS classes, the data-* attribute of the DOM element to store the state
|
|
264
|
+
$headerPin.addEventListener('click', () => {
|
|
265
|
+
let newText = toggleText($headerPin.dataset.attachement, ['PINNED', 'UNPINNED'])
|
|
266
|
+
$headerPin.classList.toggle('og-OFF')
|
|
267
|
+
$headerPin.dataset.attachement = newText
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
// Header double click
|
|
271
|
+
$header.addEventListener('dblclick', (e) => {
|
|
272
|
+
if ($header !== e.target) return
|
|
273
|
+
restoreInitialPos($dialog)
|
|
274
|
+
}, false)
|
|
275
|
+
|
|
276
|
+
const restoreInitialPos = (el) => {
|
|
277
|
+
el.style.top = dialogBoxInitial.top + "px";
|
|
278
|
+
el.style.left = dialogBoxInitial.left + "px";
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Header mousedown --> move dialog OR nothing
|
|
282
|
+
const { behaviour, mouseMove } = enableElmovement($dialog, this.planet)
|
|
283
|
+
|
|
284
|
+
$header.addEventListener('mousedown', (e) => {
|
|
285
|
+
if ($headerPin.dataset.attachement == 'UNPINNED') {
|
|
286
|
+
behaviour(e)
|
|
287
|
+
} else {
|
|
288
|
+
document.removeEventListener('mousemove', mouseMove)
|
|
289
|
+
}
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
$header_close.addEventListener('click', () => {
|
|
293
|
+
$dialog.classList.add('og-not-visible')
|
|
294
|
+
$menuBtn.classList.add('og-OFF')
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
$headerMinMax.addEventListener('click', () => {
|
|
298
|
+
$mainContainer.classList.toggle('og-hide')
|
|
299
|
+
$mainContainer.classList.toggle('og-minimized')
|
|
300
|
+
$dialog.classList.toggle('og-minimized')
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
return { $mainContainer, whereClickHandler }
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
buildRecords(myData, $mainContainer, depth, createLastDropZone) {
|
|
307
|
+
let planet = this.planet
|
|
308
|
+
|
|
309
|
+
// Record functions
|
|
310
|
+
const createTitle = (object) => {
|
|
311
|
+
if (object.data) {
|
|
312
|
+
return elementFactory('details', { class: 'og-layer-switcher-record-title' },
|
|
313
|
+
elementFactory('summary', {}, object.name || object.url || 'no-name'))
|
|
314
|
+
} else {
|
|
315
|
+
return elementFactory('label', { class: 'og-layer-switcher-record-title' },
|
|
316
|
+
object.name || object.properties.name || 'no-name')
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const visibility = (object, nameConcat) => {
|
|
321
|
+
if (
|
|
322
|
+
(nameConcat == 'TerrainProviders' && planet.terrain == object) ||
|
|
323
|
+
(nameConcat == 'BaseLayers' && planet.baseLayer == object) ||
|
|
324
|
+
(nameConcat == 'OverLays' && object.getVisibility() == true)
|
|
325
|
+
) {
|
|
326
|
+
return true
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const createInput = (object, depth, type, nameConcat) => {
|
|
331
|
+
if (depth > 0) {
|
|
332
|
+
return elementFactory('input', {
|
|
333
|
+
class: 'og-layer-switcher-record-input ' +
|
|
334
|
+
nameConcat, type: type || 'checkbox',
|
|
335
|
+
...(visibility(object, nameConcat) ? { checked: true } : null)
|
|
336
|
+
}, '')
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const createDropZone = (object, depth, type) => {
|
|
341
|
+
if (depth > 0 && type === 'checkbox') {
|
|
342
|
+
return elementFactory('div', { class: 'og-layer-switcher-dropZone' },)
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Record listeners
|
|
347
|
+
const inputListener = (input, nameConcat, object, title) => {
|
|
348
|
+
input ? input.addEventListener('click', () => inputClick(input, nameConcat, object, title)) : null
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const inputClick = (input, nameConcat, object, title) => {
|
|
352
|
+
let siblings = [...document.querySelectorAll('.og-layer-switcher-record-input' + '.' + nameConcat)]
|
|
353
|
+
if (nameConcat == 'BaseLayers') {
|
|
354
|
+
siblings.forEach(sibling => sibling.checked = false)
|
|
355
|
+
input.checked = true
|
|
356
|
+
object.setVisibility(true)
|
|
357
|
+
} else if (nameConcat == 'TerrainProviders') {
|
|
358
|
+
siblings.forEach(sibling => sibling.checked = false)
|
|
359
|
+
input.checked = true
|
|
360
|
+
planet.setTerrain(object)
|
|
361
|
+
} else if (nameConcat == 'Overlays') {
|
|
362
|
+
object.setVisibility(input.checked)
|
|
363
|
+
// Handle any entities contained in layer
|
|
364
|
+
let entities = object._entities
|
|
365
|
+
let inputs = [...title.querySelectorAll('input')]
|
|
366
|
+
entities ? object._entities.forEach((entity, index) => {
|
|
367
|
+
inputs[index].checked = entity.getVisibility()
|
|
368
|
+
}) : null
|
|
369
|
+
} else {
|
|
370
|
+
object.setVisibility(input.checked)
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const titleListener = (title, object) => {
|
|
375
|
+
title ? title.addEventListener('dblclick', () => titleDoubleClick(object)) : null
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const titleDoubleClick = (object) => {
|
|
379
|
+
planet.flyExtent(object.getExtent())
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Record listeners - dragging behaviour
|
|
383
|
+
const recordDragStart = (record) => {
|
|
384
|
+
record.addEventListener('dragstart', () => {
|
|
385
|
+
record.classList.add('og-dragging');
|
|
386
|
+
})
|
|
387
|
+
}
|
|
388
|
+
const recordDragEnd = (record) => {
|
|
389
|
+
record.addEventListener('dragend', () => {
|
|
390
|
+
record.classList.remove('og-dragging');
|
|
391
|
+
})
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const recordDrag = (record) => {
|
|
395
|
+
recordDragStart(record)
|
|
396
|
+
recordDragEnd(record)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
const dropZonedragOver = (dropZone) => {
|
|
401
|
+
dropZone.addEventListener('dragover', (e) => {
|
|
402
|
+
e.preventDefault()
|
|
403
|
+
dropZone.classList.add('og-drag-over')
|
|
404
|
+
})
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const dropZonedragLeave = (dropZone) => {
|
|
408
|
+
dropZone.addEventListener('dragleave', (e) => {
|
|
409
|
+
e.preventDefault();
|
|
410
|
+
dropZone.classList.remove('og-drag-over');
|
|
411
|
+
})
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// TODO in case layer entities will have dropZones I will have to modify this
|
|
415
|
+
const dropZonedrop = (dropZone) => {
|
|
416
|
+
dropZone.addEventListener('drop', (e) => {
|
|
417
|
+
let overlayContainer = document.body.querySelector('div.og-depth-0:nth-child(3) > details:nth-child(1)')
|
|
418
|
+
let dropZones = [...document.querySelectorAll('.og-layer-switcher-dropZone')];
|
|
419
|
+
e.preventDefault();
|
|
420
|
+
dropZone.classList.remove('og-drag-over');
|
|
421
|
+
let selectedLayerRecord = document.querySelector('.og-dragging');
|
|
422
|
+
// Get position of drop zone - last is a special case
|
|
423
|
+
let pos = dropZones.indexOf(dropZone)
|
|
424
|
+
if (pos < dropZones.length - 1) { // not last
|
|
425
|
+
overlayContainer.insertBefore(selectedLayerRecord, dropZone.parentElement); // Appear before the parent element
|
|
426
|
+
|
|
427
|
+
} else { // last
|
|
428
|
+
overlayContainer.insertBefore(selectedLayerRecord, dropZone); // Appear before last (fixed) dropzone element
|
|
429
|
+
}
|
|
430
|
+
indicesPerDialogOrder();
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const indicesPerDialogOrder = () => { // See how user has placed overlays in switcher and change ZIndexes accordingly (start 10000, go down 100)
|
|
435
|
+
let records = [...document.querySelectorAll('.og-layer-switcher-record.og-depth-1.Overlays')]
|
|
436
|
+
let ids = records.map(x => x.id)
|
|
437
|
+
let layers = planet.layers
|
|
438
|
+
|
|
439
|
+
let overlays = layers.filter(x => !x.isBaseLayer());
|
|
440
|
+
let visible_overlays = [...overlays.filter(x => x.displayInLayerSwitcher)];
|
|
441
|
+
for (let i = 0; i < ids.length; i++) {
|
|
442
|
+
let the_layer = visible_overlays.filter(x => x.getID() == ids[i]);
|
|
443
|
+
//
|
|
444
|
+
//TODO: No need to set zIndexes manually, just change the order in planet container.
|
|
445
|
+
//
|
|
446
|
+
the_layer[0].setZIndex(10000 - i * 100);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const dropZoneBehaviour = (dropZone) => {
|
|
451
|
+
dropZonedragOver(dropZone)
|
|
452
|
+
dropZonedragLeave(dropZone)
|
|
453
|
+
dropZonedrop(dropZone)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const { sectionsOpening } = this.getUserPrefs()
|
|
457
|
+
// Actual record creation
|
|
458
|
+
const createChildren = (object, $outerWrapper, depth) => {
|
|
459
|
+
let data = object.data || object._entities
|
|
460
|
+
if (data) {
|
|
461
|
+
data.map((x, index) => {
|
|
462
|
+
let nameConcat = object.name ? object.name.replace(/\s/g, '') : null
|
|
463
|
+
let $dropZone = createDropZone(x, depth, object.input)
|
|
464
|
+
let $input = createInput(x, depth, object.input, nameConcat)
|
|
465
|
+
let $title = createTitle(x)
|
|
466
|
+
$input ? inputListener($input, nameConcat, x, $title) : null
|
|
467
|
+
$title && depth > 0 ? titleListener($title, x) : null // need depth > 0 cause to avoid calling on main sections
|
|
468
|
+
$title && depth == 0 && sectionsOpening == true ? $title.setAttribute("open", "") : null // open summaries of depth 0
|
|
469
|
+
let $innerWrapper = elementFactory('div', {
|
|
470
|
+
id: depth == 1 ? x._id : null,
|
|
471
|
+
class: 'og-layer-switcher-record ' + 'og-depth-'
|
|
472
|
+
+ depth + (nameConcat ? ' ' + nameConcat : ''),
|
|
473
|
+
draggable: $dropZone ? true : false
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
$dropZone ? dropZoneBehaviour($dropZone) : null
|
|
477
|
+
$dropZone ? recordDrag($innerWrapper) : null
|
|
478
|
+
$dropZone ? $innerWrapper.appendChild($dropZone) : null
|
|
479
|
+
|
|
480
|
+
$input ? $innerWrapper.appendChild($input) : null
|
|
481
|
+
$title ? $innerWrapper.appendChild($title) : null
|
|
482
|
+
$outerWrapper.appendChild($innerWrapper)
|
|
483
|
+
|
|
484
|
+
// Is last time in data array? Make another dropZone - fixed, not movable
|
|
485
|
+
if (index === data.length - 1 && createLastDropZone === true) {
|
|
486
|
+
let $dropZone = createDropZone(x, depth, object.input)
|
|
487
|
+
$dropZone ? dropZoneBehaviour($dropZone) : null
|
|
488
|
+
$dropZone ? recordDrag($innerWrapper) : null
|
|
489
|
+
$dropZone ? $outerWrapper.appendChild($dropZone) : null
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
createChildren(x, $title, depth + 1)
|
|
493
|
+
})
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
createChildren(myData, $mainContainer, depth)
|
|
497
|
+
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
removeRecords() {
|
|
501
|
+
let records = [...document.querySelectorAll('.og-layer-switcher-record.og-depth-0')]
|
|
502
|
+
records.forEach(record => record.remove())
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export { LayerSwitcher }
|