renusify 1.4.3 → 1.4.4

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.
Files changed (43) hide show
  1. package/components/app/index.vue +1 -10
  2. package/components/chip/style.scss +0 -1
  3. package/components/codeEditor/highlightHtml.vue +8 -2
  4. package/components/codeEditor/index.vue +13 -55
  5. package/components/codeEditor/mixin.js +18 -4
  6. package/components/form/camInput.vue +6 -2
  7. package/components/form/input.vue +1 -1
  8. package/components/form/mask-input.vue +2 -2
  9. package/components/form/text-area.vue +1 -1
  10. package/components/form/text-editor/index.vue +0 -1
  11. package/components/form/timepicker/index.vue +18 -16
  12. package/components/form/unit-input.vue +1 -0
  13. package/components/formCreator/index.vue +7 -20
  14. package/components/index.js +1 -1
  15. package/components/infinite/index.vue +9 -6
  16. package/components/map/index.vue +52 -20
  17. package/components/map/leaflet.css +511 -397
  18. package/components/map/route.vue +570 -560
  19. package/components/map/select.vue +64 -48
  20. package/components/message/index.vue +22 -21
  21. package/components/modal/index.vue +20 -7
  22. package/components/modal/style.scss +17 -14
  23. package/components/{app/notify → notify}/index.vue +21 -29
  24. package/components/{app/notify → notify}/notification.vue +10 -10
  25. package/components/notify/notify.js +27 -0
  26. package/components/searchBox/index.vue +30 -12
  27. package/components/slider/index.vue +1 -0
  28. package/components/table/index.vue +366 -367
  29. package/components/table/style.scss +1 -4
  30. package/components/tabs/index.vue +9 -23
  31. package/components/timeAgo/index.vue +4 -1
  32. package/components/tour/index.vue +237 -222
  33. package/components/tree/index.vue +135 -136
  34. package/components/tree/tree-element.vue +17 -3
  35. package/directive/index.js +1 -2
  36. package/directive/mask/index.js +1 -4
  37. package/directive/skeleton/index.js +27 -0
  38. package/directive/skeleton/style.scss +37 -0
  39. package/index.js +14 -9
  40. package/package.json +1 -1
  41. package/style/transitions.scss +6 -116
  42. package/tools/helper.js +20 -0
  43. package/components/app/notify/notify.js +0 -28
@@ -1,575 +1,585 @@
1
1
  <template>
2
- <r-container :class="`${$r.prefix}map-route sheet sheet-tile pa-0`">
3
- <r-row class="no-gutters">
4
- <r-col class="col-12 sm-9">
5
- <r-map :model-value="center" @map="handleMapEvent" @leaflet="handleLEvent" :height="height" :zoom="15"
6
- :dark-mode="darkMode" search-box></r-map>
7
- </r-col>
8
- <r-col class="overflow-y-auto col-12 sm-3" :style="'height: '+height">
9
- <div class="pa-2">
10
- <slot name="header" :time="time" :distance="distance">
11
- <div class="title">{{$helper.ifHas(modelValue,'------','summary','name')}}</div>
12
- <r-divider class="my-3"></r-divider>
13
- <div>{{time||'---'}}</div>
14
- <div>{{distance||'0 km'}}</div>
15
- </slot>
16
- <slot name="points" :points="points" :open="open" :to="to" :del="del" :add="add">
17
- <transition-group name="slide-up">
18
- <div class="route-point px-2 py-1 my-2 br-lg text-end"
19
- v-for="(point,i) in points" :key="i">
20
- <div class="d-flex">
21
- <span class="mt-1 title">{{pos(points_keys.indexOf(i))}}</span>
22
- <r-spacer></r-spacer>
23
- <r-btn v-if="editable && i!==points_keys[0]" icon text
24
- @click.prevent="to(points_keys.indexOf(i),points_keys.indexOf(i)-1)">
25
- <r-icon v-html="$r.icons.arrow_up"></r-icon>
26
- </r-btn>
27
- <r-btn v-if="editable && i!==points_keys[points_keys.length-1]" icon text
28
- @click.prevent="to(points_keys.indexOf(i),points_keys.indexOf(i)+1)">
29
- <r-icon v-html="$r.icons.arrow_down"></r-icon>
30
- </r-btn>
31
- <r-btn v-if="editable" icon class="color-error-text" text @click.prevent="del(i)">
32
- <r-icon v-html="$r.icons.delete"></r-icon>
33
- </r-btn>
34
- </div>
35
- <div class="py-2 route-name text-start" @click.prevent="open(points_keys.indexOf(i))">
36
- <r-icon v-html="$r.icons.map_marker"></r-icon>
37
- {{$helper.ifHas(modelValue, '', 'waypoints', points_keys.indexOf(i), 'name')}}
38
- </div>
39
- </div>
40
- </transition-group>
41
- <r-btn v-if="editable && points_keys.length<maxPoints" class="color-success-text" outlined rounded @click.prevent="add" block
42
- :loading="loading">
43
- <r-icon v-html="$r.icons.plus"></r-icon>
44
- <span>{{$t('map_new_point','renusify')}}</span>
45
- </r-btn>
46
- </slot>
47
- <slot name="footer"></slot>
2
+ <r-container :class="`${$r.prefix}map-route sheet sheet-tile pa-0`">
3
+ <r-row class="no-gutters">
4
+ <r-col class="col-12 sm-9">
5
+ <r-map :dark-mode="darkMode" :height="height" :model-value="center" :zoom="15" search-box
6
+ @leaflet="handleLEvent" @map="handleMapEvent"></r-map>
7
+ </r-col>
8
+ <r-col :style="'height: '+height" class="overflow-y-auto col-12 sm-3">
9
+ <div class="pa-2">
10
+ <slot :distance="distance" :time="time" name="header">
11
+ <div class="title">{{ $helper.ifHas(modelValue, '------', 'summary', 'name') }}</div>
12
+ <r-divider class="my-3"></r-divider>
13
+ <div>{{ time || '---' }}</div>
14
+ <div>{{ distance || '0 km' }}</div>
15
+ </slot>
16
+ <slot :add="add" :del="del" :open="open" :points="points" :to="to" name="points">
17
+ <transition-group name="slide-up">
18
+ <div v-for="(point,i) in points"
19
+ :key="i" class="route-point px-2 py-1 my-2 br-lg text-end">
20
+ <div class="d-flex">
21
+ <span class="mt-1 title">{{ pos(points_keys.indexOf(i)) }}</span>
22
+ <r-spacer></r-spacer>
23
+ <r-btn v-if="editable && i!==points_keys[0]" icon text
24
+ @click.prevent="to(points_keys.indexOf(i),points_keys.indexOf(i)-1)">
25
+ <r-icon v-html="$r.icons.arrow_up"></r-icon>
26
+ </r-btn>
27
+ <r-btn v-if="editable && i!==points_keys[points_keys.length-1]" icon text
28
+ @click.prevent="to(points_keys.indexOf(i),points_keys.indexOf(i)+1)">
29
+ <r-icon v-html="$r.icons.arrow_down"></r-icon>
30
+ </r-btn>
31
+ <r-btn v-if="editable" class="color-error-text" icon text @click.prevent="del(i)">
32
+ <r-icon v-html="$r.icons.delete"></r-icon>
33
+ </r-btn>
48
34
  </div>
49
- </r-col>
50
- </r-row>
51
- </r-container>
35
+ <div class="py-2 route-name text-start" @click.prevent="open(points_keys.indexOf(i))">
36
+ <r-icon v-html="$r.icons.map_marker"></r-icon>
37
+ {{ $helper.ifHas(modelValue, '', 'waypoints', points_keys.indexOf(i), 'name') }}
38
+ </div>
39
+ </div>
40
+ </transition-group>
41
+ <r-btn v-if="editable && points_keys.length<maxPoints" :loading="loading" block class="color-success-text"
42
+ outlined rounded
43
+ @click.prevent="add">
44
+ <r-icon v-html="$r.icons.plus"></r-icon>
45
+ <span>{{ $t('map_new_point', 'renusify') }}</span>
46
+ </r-btn>
47
+ </slot>
48
+ <slot name="footer"></slot>
49
+ </div>
50
+ </r-col>
51
+ </r-row>
52
+ </r-container>
52
53
  </template>
53
54
  <script>
54
- export default {
55
- name: 'r-map-route',
56
- props: {
57
- modelValue: Object,
58
- by: {
59
- type: String, default: 'car', validator: function (value) {
60
- return ['car', 'foot', 'bike'].indexOf(value) !== -1
61
- }
62
- },
63
- height: {type: String, default: "500px"},
64
- marginTime: {type: Number, default: 1},
65
- color: {
66
- type: Array, default: () => {
67
- return []
68
- }
69
- },
70
- maxPoints:{type:Number,default:3},
71
- darkMode: Boolean,
72
- editable: Boolean
73
- },
74
- emits:['update:modelValue'],
75
- data() {
76
- return {
77
- loading: false,
78
- timeout_id: null,
79
- req_id: null,
80
- map: null,
81
- L: null,
82
- center: [],
83
- markers: null,
84
- lines: null,
85
- routing: {},
86
- points: this.$helper.ifHas(this.modelValue, {}, 'points')
87
- }
88
- },
89
- created() {
90
- this.get()
91
- if(!this.$r.icons.map_marker){
92
- this.$r.icons.map_marker='<path fill="currentColor" d="M12 6.5A2.5 2.5 0 0 1 14.5 9a2.5 2.5 0 0 1-2.5 2.5A2.5 2.5 0 0 1 9.5 9A2.5 2.5 0 0 1 12 6.5M12 2a7 7 0 0 1 7 7c0 5.25-7 13-7 13S5 14.25 5 9a7 7 0 0 1 7-7m0 2a5 5 0 0 0-5 5c0 1 0 3 5 9.71C17 12 17 10 17 9a5 5 0 0 0-5-5Z"/>'
93
- }
94
- },
95
- computed: {
96
- points_keys() {
97
- return Object.keys(this.points)
98
- },
99
- points_vals() {
100
- return Object.values(this.points)
101
- },
102
- time() {
103
- return this.timeHumanity(this.$helper.ifHas(this.modelValue, 0, 'summary', 'time'))
104
- },
105
- distance() {
106
- if (!this.$helper.ifHas(this.modelValue, false, 'summary', 'distance')) {
107
- return ''
108
- }
109
-
110
- return ((this.modelValue.summary.distance / 1000).toFixed(2)) + ' km'
55
+ export default {
56
+ name: 'r-map-route',
57
+ props: {
58
+ modelValue: Object,
59
+ by: {
60
+ type: String, default: 'car', validator: function (value) {
61
+ return ['car', 'foot', 'bike'].indexOf(value) !== -1
62
+ }
63
+ },
64
+ height: {type: String, default: "500px"},
65
+ marginTime: {type: Number, default: 1},
66
+ color: {
67
+ type: Array, default: () => {
68
+ return []
69
+ }
70
+ },
71
+ maxPoints: {type: Number, default: 3},
72
+ darkMode: Boolean,
73
+ editable: Boolean
74
+ },
75
+ emits: ['update:modelValue'],
76
+ data() {
77
+ return {
78
+ loading: false,
79
+ timeout_id: null,
80
+ req_id: null,
81
+ map: null,
82
+ L: null,
83
+ center: [],
84
+ markers: null,
85
+ lines: null,
86
+ routing: {},
87
+ points: this.$helper.ifHas(this.modelValue, {}, 'points')
88
+ }
89
+ },
90
+ created() {
91
+ this.get()
92
+ if (!this.$r.icons.map_marker) {
93
+ this.$r.icons.map_marker = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24\" viewBox="0 0 24 24"><path fill="currentColor" d="M12 6.5A2.5 2.5 0 0 1 14.5 9a2.5 2.5 0 0 1-2.5 2.5A2.5 2.5 0 0 1 9.5 9A2.5 2.5 0 0 1 12 6.5M12 2a7 7 0 0 1 7 7c0 5.25-7 13-7 13S5 14.25 5 9a7 7 0 0 1 7-7m0 2a5 5 0 0 0-5 5c0 1 0 3 5 9.71C17 12 17 10 17 9a5 5 0 0 0-5-5Z"/></svg>'
94
+ }
95
+ },
96
+ computed: {
97
+ points_keys() {
98
+ return Object.keys(this.points)
99
+ },
100
+ points_vals() {
101
+ return Object.values(this.points)
102
+ },
103
+ time() {
104
+ return this.timeHumanity(this.$helper.ifHas(this.modelValue, 0, 'summary', 'time'))
105
+ },
106
+ distance() {
107
+ if (!this.$helper.ifHas(this.modelValue, false, 'summary', 'distance')) {
108
+ return ''
109
+ }
110
+
111
+ return ((this.modelValue.summary.distance / 1000).toFixed(2)) + ' km'
112
+ },
113
+ iconOrigin() {
114
+ return require('./images/origin.png')
115
+ },
116
+ iconPoint() {
117
+ return require('./images/point.png')
118
+ },
119
+ iconDestination() {
120
+ return require('./images/destination.png')
121
+ }
122
+ },
123
+ methods: {
124
+ pos(i) {
125
+ let n = i + 1
126
+ if (i === 0) {
127
+ n = this.$t('map_origin', 'renusify')
128
+ } else if (i === this.points_vals.length - 1) {
129
+ n = this.$t('map_destination', 'renusify')
130
+ }
131
+ return this.$t(['map_point', [n]], 'renusify')
132
+ },
133
+ name(i) {
134
+ return this.pos(i) + ': ' + this.$helper.ifHas(this.modelValue, '', 'waypoints', i, 'name')
135
+ },
136
+ open(i) {
137
+ this.center = Object.values(Object.values(this.markers._layers)[i]._latlng)
138
+ Object.values(this.markers._layers)[i].openPopup()
139
+ },
140
+ del(i) {
141
+ delete this.points[i]
142
+ this.get()
143
+ },
144
+ array_move(arr, old, new_pos) {
145
+ if (new_pos >= arr.length) {
146
+ var k = new_pos - arr.length + 1;
147
+ while (k--) {
148
+ arr.push(undefined);
149
+ }
150
+ }
151
+ arr.splice(new_pos, 0, arr.splice(old, 1)[0]);
152
+ return arr
153
+ },
154
+ to(i, pos) {
155
+ const val = this.array_move(this.points_vals, i, pos)
156
+ const key = this.array_move(this.points_keys, i, pos)
157
+ const way = this.array_move(this.modelValue.waypoints, i, pos)
158
+ let res = {}
159
+ key.forEach((item, i) => {
160
+ res[item] = val[i]
161
+ })
162
+ this.points = res
163
+ this.$emit('update:modelValue', {
164
+ 'points': this.points,
165
+ 'summary': this.modelValue.summary,
166
+ 'waypoints': way
167
+ })
168
+ setTimeout(() => {
169
+ this.get()
170
+ }, 800)
171
+ },
172
+ openLastPopup(n = 0) {
173
+ clearTimeout(this.timeout_id)
174
+ if (Object.values(this.markers._layers)[this.points_vals.length - 1] === undefined) {
175
+ this.timeout_id = setTimeout(() => {
176
+ if (n < 10) {
177
+ this.openLastPopup(n + 1)
178
+ }
179
+ }, 1000)
180
+ return
181
+ }
182
+ Object.values(this.markers._layers)[this.points_vals.length - 1].openPopup()
183
+ },
184
+ add() {
185
+ this.loading = true
186
+ this.points[this.$helper.uniqueId(12)] = Object.values(this.map.getCenter())
187
+ this.get()
188
+ this.openLastPopup()
189
+ this.loading = false
190
+ },
191
+ timeHumanity(seconds) {
192
+ const numyears = Math.floor(seconds / 31536000);
193
+ const numdays = Math.floor((seconds % 31536000) / 86400);
194
+ const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
195
+ const numminutes = Math.ceil((((seconds % 31536000) % 86400) % 3600) / 60);
196
+ let res = ''
197
+ if (numyears > 0) {
198
+ res += numyears + ' ' + this.$t("years", 'renusify')
199
+ }
200
+ if (numdays > 0) {
201
+ res += ' ' + numdays + ' ' + this.$t("days", 'renusify')
202
+ }
203
+ if (numhours > 0) {
204
+ res += ' ' + numhours + ' ' + this.$t("hours", 'renusify')
205
+ }
206
+ if (numminutes > 0) {
207
+ res += ' ' + numminutes + ' ' + this.$t("minutes", 'renusify')
208
+ }
209
+ return res
210
+ },
211
+ handleLEvent(e) {
212
+ this.L = e
213
+ },
214
+ handleMapEvent(e) {
215
+ this.map = e
216
+ if (this.points_vals.length > 0) {
217
+ this.center = this.points_vals[0]
218
+ }
219
+ },
220
+ drawMarkers() {
221
+ if (!this.L) {
222
+ return
223
+ }
224
+ if (this.markers) {
225
+ this.map.removeLayer(this.markers)
226
+ }
227
+ const all = []
228
+ const that = this
229
+
230
+ this.points_vals.forEach((point, i) => {
231
+ let icon = this.iconPoint
232
+ if (i === 0) {
233
+ icon = this.iconOrigin
234
+ } else if (i === this.points_vals.length - 1) {
235
+ icon = this.iconDestination
236
+ }
237
+ let m = new this.L.Marker(point, {
238
+ draggable: this.editable,
239
+ index: this.points_keys[i],
240
+ icon: new this.L.icon({
241
+ iconUrl: icon,
242
+ iconSize: [50, 50],
243
+ iconAnchor: [25, 50],
244
+ popupAnchor: [0, -40]
245
+ })
246
+ })
247
+ m.bindPopup(this.$t('map_move_marker', 'renusify') + '<hr>' + this.name(i))
248
+ m.on('drag', function (e) {
249
+ that.points[e.target.options.index] = Object.values(e.latlng)
250
+ });
251
+ m.on('dragend', function (e) {
252
+ that.get()
253
+ });
254
+ all.push(m)
255
+ })
256
+ this.markers = this.L.layerGroup(all);
257
+ this.map.addLayer(this.markers);
258
+ },
259
+ draw() {
260
+ if (this.routing.code !== 'Ok' || !this.L || !this.routing.routes) {
261
+ return
262
+ }
263
+
264
+ let alts = {'points': this.points, 'routes': [], 'summary': {'name': '', 'time': 0, 'distance': 0}}
265
+ const lng = Object.values(this.routing.routes).length
266
+ for (let i = 0; i < lng; i++) {
267
+ let route = this._convertRoute(this.routing.routes[i]);
268
+ alts.routes.push(route);
269
+ alts.summary.name = route['name']
270
+ alts.summary.time += parseFloat(route.summary.total_time) * this.marginTime
271
+ alts.summary.distance += parseFloat(route.summary.total_distance)
272
+ }
273
+ alts.waypoints = this.routing.waypoints
274
+ alts.waypoints.forEach((item) => {
275
+ delete item.hint
276
+ delete item.location
277
+ })
278
+
279
+ this.$emit('update:modelValue', {
280
+ 'points': alts.points,
281
+ 'summary': alts.summary,
282
+ 'waypoints': alts.waypoints
283
+ })
284
+ let l = []
285
+ alts.routes[0].waypointIndices.forEach((item, i) => {
286
+ if (i < alts.routes[0].waypointIndices.length - 1) {
287
+ const p = alts.routes[0].coordinates.slice(item, alts.routes[0].waypointIndices[i + 1])
288
+ let color = 'red'
289
+ if (this.color[i]) {
290
+ color = this.color[i]
291
+ } else if (this.color.length > 0) {
292
+ color = i % 2 === 0 ? this.color[0] : (this.color[1] || this.color[0])
293
+ }
294
+
295
+ l.push(new L.polyline(p, {color: color, weight: 5}))
296
+ }
297
+ })
298
+ this.lines = L.layerGroup(l);
299
+ setTimeout(() => {
300
+ this.map.addLayer(this.lines);
301
+ this.drawMarkers()
302
+ }, 1)
303
+ },
304
+ get() {
305
+ this.$emit('update:modelValue', {
306
+ 'points': this.points,
307
+ 'summary': {},
308
+ 'waypoints': []
309
+ })
310
+ this.drawMarkers()
311
+ if (this.lines) {
312
+ this.map.removeLayer(this.lines);
313
+ }
314
+ if (this.points_vals.length < 2) {
315
+ return
316
+ }
317
+ const that = this
318
+ let url = 'https://routing.openstreetmap.de/routed-' + this.by + '/route/v1/driving/'
319
+ this.points_vals.forEach(point => {
320
+ url += point[1] + ',' + point[0] + ';'
321
+ })
322
+ url = url.substr(0, url.length - 1) + '?overview=false&steps=true'
323
+
324
+ this.corslite(url, function (err, resp) {
325
+ if (!err) {
326
+ try {
327
+ that.routing = JSON.parse(resp.responseText);
328
+ that.draw()
329
+ } catch (e) {
330
+ console.error('Error parsing OSRM response: ' + e.toString())
331
+ }
332
+ } else {
333
+ console.error('HTTP request failed: ' + err.type +
334
+ (err.target && err.target.status ? ' HTTP ' + err.target.status + ': ' + err.target.statusText : ''))
335
+ }
336
+ })
337
+ },
338
+ corslite(url, callback) {
339
+ if (typeof window.XMLHttpRequest === 'undefined') {
340
+ return callback(Error('Browser not supported'));
341
+ }
342
+ if (this.req_id) {
343
+ this.req_id.abort()
344
+ }
345
+ let x = new window.XMLHttpRequest();
346
+
347
+ function isSuccessful(status) {
348
+ return status >= 200 && status < 300 || status === 304;
349
+ }
350
+
351
+ function loaded() {
352
+ if (
353
+ // XDomainRequest
354
+ x.status === undefined ||
355
+ // modern browsers
356
+ isSuccessful(x.status)) callback.call(x, null, x);
357
+ else callback.call(x, x, null);
358
+ }
359
+
360
+ if ('onload' in x) {
361
+ x.onload = loaded;
362
+ } else {
363
+ x.onreadystatechange = function readystate() {
364
+ if (x.readyState === 4) {
365
+ loaded();
366
+ }
367
+ };
368
+ }
369
+ x.timeout = 7000;
370
+ x.onerror = function error(e) {
371
+ callback.call(this, e || true, null);
372
+ callback = function () {
373
+ };
374
+ };
375
+
376
+ x.onprogress = function () {
377
+ };
378
+
379
+ x.ontimeout = function (e) {
380
+ callback.call(this, e, null);
381
+ callback = function () {
382
+ };
383
+ };
384
+
385
+ x.onabort = function (e) {
386
+ callback.call(this, e, null);
387
+ callback = function () {
388
+ };
389
+ };
390
+
391
+ x.open('GET', url, true);
392
+
393
+ x.send(null);
394
+ this.req_id = x
395
+ return x;
396
+ },
397
+ _convertRoute: function (responseRoute) {
398
+ var result = {
399
+ name: '',
400
+ coordinates: [],
401
+ instructions: [],
402
+ summary: {
403
+ total_distance: responseRoute.distance,
404
+ total_time: responseRoute.duration
111
405
  }
112
- },
113
- methods: {
114
- pos(i) {
115
- let n = i + 1
116
- if (i === 0) {
117
- n = this.$t('map_origin','renusify')
118
- } else if (i === this.points_vals.length - 1) {
119
- n = this.$t('map_destination','renusify')
120
- }
121
- return this.$t(['map_point', [n]],'renusify')
122
- },
123
- name(i) {
124
- return this.pos(i) + ': ' + this.$helper.ifHas(this.modelValue, '', 'waypoints', i, 'name')
125
- },
126
- open(i) {
127
- this.center = Object.values(Object.values(this.markers._layers)[i]._latlng)
128
- Object.values(this.markers._layers)[i].openPopup()
129
- },
130
- del(i) {
131
- delete this.points[i]
132
- this.get()
133
- },
134
- array_move(arr, old, new_pos) {
135
- if (new_pos >= arr.length) {
136
- var k = new_pos - arr.length + 1;
137
- while (k--) {
138
- arr.push(undefined);
139
- }
140
- }
141
- arr.splice(new_pos, 0, arr.splice(old, 1)[0]);
142
- return arr
143
- },
144
- to(i, pos) {
145
- const val = this.array_move(this.points_vals, i, pos)
146
- const key = this.array_move(this.points_keys, i, pos)
147
- const way = this.array_move(this.modelValue.waypoints, i, pos)
148
- let res = {}
149
- key.forEach((item, i) => {
150
- res[item] = val[i]
151
- })
152
- this.points = res
153
- this.$emit('update:modelValue',{
154
- 'points': this.points,
155
- 'summary': this.modelValue.summary,
156
- 'waypoints': way
157
- })
158
- setTimeout(() => {
159
- this.get()
160
- }, 800)
161
- },
162
- openLastPopup(n = 0) {
163
- clearTimeout(this.timeout_id)
164
- if (Object.values(this.markers._layers)[this.points_vals.length - 1] === undefined) {
165
- this.timeout_id = setTimeout(() => {
166
- if (n < 10) {
167
- this.openLastPopup(n + 1)
168
- }
169
- }, 1000)
170
- return
171
- }
172
- Object.values(this.markers._layers)[this.points_vals.length - 1].openPopup()
173
- },
174
- add() {
175
- this.loading = true
176
- this.points[this.$helper.uniqueId(12)] = Object.values(this.map.getCenter())
177
- this.get()
178
- this.openLastPopup()
179
- this.loading = false
180
- },
181
- timeHumanity(seconds) {
182
- const numyears = Math.floor(seconds / 31536000);
183
- const numdays = Math.floor((seconds % 31536000) / 86400);
184
- const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
185
- const numminutes = Math.ceil((((seconds % 31536000) % 86400) % 3600) / 60);
186
- let res = ''
187
- if (numyears > 0) {
188
- res += numyears + ' ' + this.$t("years", 'renusify')
189
- }
190
- if (numdays > 0) {
191
- res += ' ' + numdays + ' ' + this.$t("days", 'renusify')
192
- }
193
- if (numhours > 0) {
194
- res += ' ' + numhours + ' ' + this.$t("hours", 'renusify')
195
- }
196
- if (numminutes > 0) {
197
- res += ' ' + numminutes + ' ' + this.$t("minutes", 'renusify')
198
- }
199
- return res
200
- },
201
- handleLEvent(e) {
202
- this.L = e
203
- },
204
- handleMapEvent(e) {
205
- this.map = e
206
- if (this.points_vals.length > 0) {
207
- this.center = this.points_vals[0]
208
- }
209
- },
210
- drawMarkers() {
211
- if (!this.L) {
212
- return
213
- }
214
- if (this.markers) {
215
- this.map.removeLayer(this.markers)
216
- }
217
- const all = []
218
- const that = this
219
-
220
- this.points_vals.forEach((point, i) => {
221
- let icon = '/storage/img/map/images/point.png?w=50&h=50'
222
- if (i === 0) {
223
- icon = '/storage/img/map/images/origin.png?w=50&h=50'
224
- } else if (i === this.points_vals.length - 1) {
225
- icon = '/storage/img/map/images/destination.png?w=50&h=50'
226
- }
227
- let m = new this.L.Marker(point, {
228
- draggable: this.editable,
229
- index: this.points_keys[i],
230
- icon: new this.L.icon({
231
- iconUrl: icon,
232
- iconSize: [50, 50],
233
- iconAnchor: [25, 50],
234
- popupAnchor: [0, -40]
235
- })
236
- })
237
- m.bindPopup(this.$t('map_move_marker','renusify') + '<hr>' + this.name(i))
238
- m.on('drag', function (e) {
239
- that.points[e.target.options.index] = Object.values(e.latlng)
240
- });
241
- m.on('dragend', function (e) {
242
- that.get()
243
- });
244
- all.push(m)
245
- })
246
- this.markers = this.L.layerGroup(all);
247
- this.map.addLayer(this.markers);
248
- },
249
- draw() {
250
- if (this.routing.code !== 'Ok' || !this.L || !this.routing.routes) {
251
- return
252
- }
253
-
254
- let alts = {'points': this.points, 'routes': [], 'summary': {'name': '', 'time': 0, 'distance': 0}}
255
- const lng=this.routing.routes.length
256
- for (let i = 0; i < lng; i++) {
257
- let route = this._convertRoute(this.routing.routes[i]);
258
- alts.routes.push(route);
259
- alts.summary.name = route['name']
260
- alts.summary.time += parseFloat(route.summary.total_time) * this.marginTime
261
- alts.summary.distance += parseFloat(route.summary.total_distance)
262
- }
263
- alts.waypoints = this.routing.waypoints
264
- alts.waypoints.forEach((item) => {
265
- delete item.hint
266
- delete item.location
267
- })
268
-
269
- this.$emit('update:modelValue', {
270
- 'points': alts.points,
271
- 'summary': alts.summary,
272
- 'waypoints': alts.waypoints
273
- })
274
- let l = []
275
- alts.routes[0].waypointIndices.forEach((item, i) => {
276
- if (i < alts.routes[0].waypointIndices.length - 1) {
277
- const p = alts.routes[0].coordinates.slice(item, alts.routes[0].waypointIndices[i + 1])
278
- let color = 'red'
279
- if (this.color[i]) {
280
- color = this.color[i]
281
- } else if (this.color.length > 0) {
282
- color = i % 2 === 0 ? this.color[0] : (this.color[1] || this.color[0])
283
- }
284
-
285
- l.push(new L.polyline(p, {color: color, weight: 5}))
286
- }
287
- })
288
- this.lines = L.layerGroup(l);
289
- setTimeout(() => {
290
- this.map.addLayer(this.lines);
291
- this.drawMarkers()
292
- }, 1)
293
- },
294
- get() {
295
- this.$emit('update:modelValue', {
296
- 'points': this.points,
297
- 'summary': {},
298
- 'waypoints': []
299
- })
300
- this.drawMarkers()
301
- if (this.lines) {
302
- this.map.removeLayer(this.lines);
303
- }
304
- if (this.points_vals.length < 2) {
305
- return
306
- }
307
- const that = this
308
- let url = 'https://routing.openstreetmap.de/routed-' + this.by + '/route/v1/driving/'
309
- this.points_vals.forEach(point => {
310
- url += point[1] + ',' + point[0] + ';'
311
- })
312
- url = url.substr(0, url.length - 1) + '?overview=false&steps=true'
313
-
314
- this.corslite(url, function (err, resp) {
315
- if (!err) {
316
- try {
317
- that.routing = JSON.parse(resp.responseText);
318
- that.draw()
319
- } catch (e) {
320
- console.error('Error parsing OSRM response: ' + e.toString())
321
- }
322
- } else {
323
- console.error('HTTP request failed: ' + err.type +
324
- (err.target && err.target.status ? ' HTTP ' + err.target.status + ': ' + err.target.statusText : ''))
325
- }
326
- })
327
- },
328
- corslite(url, callback) {
329
- if (typeof window.XMLHttpRequest === 'undefined') {
330
- return callback(Error('Browser not supported'));
331
- }
332
- if (this.req_id) {
333
- this.req_id.abort()
334
- }
335
- let x = new window.XMLHttpRequest();
336
-
337
- function isSuccessful(status) {
338
- return status >= 200 && status < 300 || status === 304;
339
- }
340
-
341
- function loaded() {
342
- if (
343
- // XDomainRequest
344
- x.status === undefined ||
345
- // modern browsers
346
- isSuccessful(x.status)) callback.call(x, null, x);
347
- else callback.call(x, x, null);
348
- }
349
-
350
- if ('onload' in x) {
351
- x.onload = loaded;
352
- } else {
353
- x.onreadystatechange = function readystate() {
354
- if (x.readyState === 4) {
355
- loaded();
356
- }
357
- };
358
- }
359
- x.timeout = 7000;
360
- x.onerror = function error(e) {
361
- callback.call(this, e || true, null);
362
- callback = function () {
363
- };
364
- };
365
-
366
- x.onprogress = function () {
367
- };
368
-
369
- x.ontimeout = function (e) {
370
- callback.call(this, e, null);
371
- callback = function () {
372
- };
373
- };
374
-
375
- x.onabort = function (e) {
376
- callback.call(this, e, null);
377
- callback = function () {
378
- };
379
- };
380
-
381
- x.open('GET', url, true);
382
-
383
- x.send(null);
384
- this.req_id = x
385
- return x;
386
- },
387
- _convertRoute: function (responseRoute) {
388
- var result = {
389
- name: '',
390
- coordinates: [],
391
- instructions: [],
392
- summary: {
393
- total_distance: responseRoute.distance,
394
- total_time: responseRoute.duration
395
- }
396
- },
397
- legNames = [],
398
- waypointIndices = [],
399
- index = 0,
400
- legCount = responseRoute.legs.length,
401
- hasSteps = responseRoute.legs[0].steps.length > 0,
402
- i,
403
- j,
404
- leg,
405
- step,
406
- geometry,
407
- type,
408
- modifier,
409
- text
410
-
411
-
412
- for (i = 0; i < legCount; i++) {
413
- leg = responseRoute.legs[i];
414
- legNames.push(leg.summary && leg.summary.charAt(0).toUpperCase() + leg.summary.substring(1));
415
- const lng=leg.steps.length
416
- for (j = 0; j < lng; j++) {
417
- step = leg.steps[j];
418
- geometry = this._decodePolyline(step.geometry);
419
- result.coordinates.push.apply(result.coordinates, geometry);
420
- type = this._maneuverToInstructionType(step.maneuver, i === legCount - 1);
421
- modifier = this._maneuverToModifier(step.maneuver);
422
- text = [step, {legCount: legCount, legIndex: i}];
423
-
424
- if (type) {
425
- if ((i == 0 && step.maneuver.type == 'depart') || step.maneuver.type == 'arrive') {
426
- waypointIndices.push(index);
427
- }
428
-
429
- result.instructions.push({
430
- type: type,
431
- distance: step.distance,
432
- time: step.duration,
433
- road: step.name,
434
- direction: this._bearingToDirection(step.maneuver.bearing_after),
435
- exit: step.maneuver.exit,
436
- index: index,
437
- mode: step.mode,
438
- modifier: modifier,
439
- text: text
440
- });
441
- }
442
-
443
- index += geometry.length;
444
- }
445
- }
446
-
447
- result.name = legNames.join(', ');
448
- if (!hasSteps) {
449
- result.coordinates = this._decodePolyline(responseRoute.geometry);
450
- } else {
451
- result.waypointIndices = waypointIndices;
452
- }
453
-
454
- return result;
455
- },
456
- _bearingToDirection: function (bearing) {
457
- var oct = Math.round(bearing / 45) % 8;
458
- return ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'][oct];
459
- },
460
- _maneuverToInstructionType: function (maneuver, lastLeg) {
461
- switch (maneuver.type) {
462
- case 'new name':
463
- return 'continue';
464
- case 'depart':
465
- return 'head';
466
- case 'arrive':
467
- return lastLeg ? 'destinationReached' : 'waypointReached';
468
- case 'roundabout':
469
- case 'rotary':
470
- return 'roundabout';
471
- case 'merge':
472
- case 'fork':
473
- case 'on ramp':
474
- case 'off ramp':
475
- case 'end of road':
476
- return this.$helper.replacer(maneuver.type, ' ', '_');
477
- default:
478
- return this.$helper.replacer(maneuver.modifier, ' ', '_');
479
- }
480
- },
481
- _maneuverToModifier: function (maneuver) {
482
- var modifier = maneuver.modifier;
483
-
484
- switch (maneuver.type) {
485
- case 'merge':
486
- case 'fork':
487
- case 'on ramp':
488
- case 'off ramp':
489
- case 'end of road':
490
- modifier = this._leftOrRight(modifier);
491
- }
492
-
493
- return modifier && this.$helper.replacer(modifier, ' ', '_');
494
- },
495
- _leftOrRight(d) {
496
- return d.indexOf('left') >= 0 ? 'left' : 'right';
497
- },
498
- polyline_decode(str, precision) {
499
- var index = 0,
500
- lat = 0,
501
- lng = 0,
502
- coordinates = [],
503
- shift = 0,
504
- result = 0,
505
- byte = null,
506
- latitude_change,
507
- longitude_change,
508
- factor = Math.pow(10, precision || 5);
509
-
510
- while (index < str.length) {
511
-
512
- // Reset shift, result, and byte
513
- byte = null;
514
- shift = 0;
515
- result = 0;
516
-
517
- do {
518
- byte = str.charCodeAt(index++) - 63;
519
- result |= (byte & 0x1f) << shift;
520
- shift += 5;
521
- } while (byte >= 0x20);
522
-
523
- latitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
524
-
525
- shift = result = 0;
526
-
527
- do {
528
- byte = str.charCodeAt(index++) - 63;
529
- result |= (byte & 0x1f) << shift;
530
- shift += 5;
531
- } while (byte >= 0x20);
532
-
533
- longitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
534
-
535
- lat += latitude_change;
536
- lng += longitude_change;
537
-
538
- coordinates.push([lat / factor, lng / factor]);
539
- }
540
-
541
- return coordinates;
542
- },
543
- _decodePolyline: function (routeGeometry) {
544
- let cs = this.polyline_decode(routeGeometry, 5),
545
- result = new Array(lng),
546
- i;
547
- const lng = cs.length;
548
- for (i = lng - 1; i >= 0; i--) {
549
- result[i] = L.latLng(cs[i]);
550
- }
551
-
552
- return result;
406
+ },
407
+ legNames = [],
408
+ waypointIndices = [],
409
+ index = 0,
410
+ legCount = responseRoute.legs.length,
411
+ hasSteps = responseRoute.legs[0].steps.length > 0,
412
+ i,
413
+ j,
414
+ leg,
415
+ step,
416
+ geometry,
417
+ type,
418
+ modifier,
419
+ text
420
+
421
+
422
+ for (i = 0; i < legCount; i++) {
423
+ leg = responseRoute.legs[i];
424
+ legNames.push(leg.summary && leg.summary.charAt(0).toUpperCase() + leg.summary.substring(1));
425
+ const lng = leg.steps.length
426
+ for (j = 0; j < lng; j++) {
427
+ step = leg.steps[j];
428
+ geometry = this._decodePolyline(step.geometry);
429
+ result.coordinates.push.apply(result.coordinates, geometry);
430
+ type = this._maneuverToInstructionType(step.maneuver, i === legCount - 1);
431
+ modifier = this._maneuverToModifier(step.maneuver);
432
+ text = [step, {legCount: legCount, legIndex: i}];
433
+
434
+ if (type) {
435
+ if ((i == 0 && step.maneuver.type == 'depart') || step.maneuver.type == 'arrive') {
436
+ waypointIndices.push(index);
553
437
  }
438
+
439
+ result.instructions.push({
440
+ type: type,
441
+ distance: step.distance,
442
+ time: step.duration,
443
+ road: step.name,
444
+ direction: this._bearingToDirection(step.maneuver.bearing_after),
445
+ exit: step.maneuver.exit,
446
+ index: index,
447
+ mode: step.mode,
448
+ modifier: modifier,
449
+ text: text
450
+ });
451
+ }
452
+
453
+ index += geometry.length;
554
454
  }
455
+ }
456
+
457
+ result.name = legNames.join(', ');
458
+ if (!hasSteps) {
459
+ result.coordinates = this._decodePolyline(responseRoute.geometry);
460
+ } else {
461
+ result.waypointIndices = waypointIndices;
462
+ }
463
+
464
+ return result;
465
+ },
466
+ _bearingToDirection: function (bearing) {
467
+ var oct = Math.round(bearing / 45) % 8;
468
+ return ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'][oct];
469
+ },
470
+ _maneuverToInstructionType: function (maneuver, lastLeg) {
471
+ switch (maneuver.type) {
472
+ case 'new name':
473
+ return 'continue';
474
+ case 'depart':
475
+ return 'head';
476
+ case 'arrive':
477
+ return lastLeg ? 'destinationReached' : 'waypointReached';
478
+ case 'roundabout':
479
+ case 'rotary':
480
+ return 'roundabout';
481
+ case 'merge':
482
+ case 'fork':
483
+ case 'on ramp':
484
+ case 'off ramp':
485
+ case 'end of road':
486
+ return this.$helper.replacer(maneuver.type, ' ', '_');
487
+ default:
488
+ return this.$helper.replacer(maneuver.modifier, ' ', '_');
489
+ }
490
+ },
491
+ _maneuverToModifier: function (maneuver) {
492
+ var modifier = maneuver.modifier;
493
+
494
+ switch (maneuver.type) {
495
+ case 'merge':
496
+ case 'fork':
497
+ case 'on ramp':
498
+ case 'off ramp':
499
+ case 'end of road':
500
+ modifier = this._leftOrRight(modifier);
501
+ }
502
+
503
+ return modifier && this.$helper.replacer(modifier, ' ', '_');
504
+ },
505
+ _leftOrRight(d) {
506
+ return d.indexOf('left') >= 0 ? 'left' : 'right';
507
+ },
508
+ polyline_decode(str, precision) {
509
+ var index = 0,
510
+ lat = 0,
511
+ lng = 0,
512
+ coordinates = [],
513
+ shift = 0,
514
+ result = 0,
515
+ byte = null,
516
+ latitude_change,
517
+ longitude_change,
518
+ factor = Math.pow(10, precision || 5);
519
+
520
+ while (index < str.length) {
521
+
522
+ // Reset shift, result, and byte
523
+ byte = null;
524
+ shift = 0;
525
+ result = 0;
526
+
527
+ do {
528
+ byte = str.charCodeAt(index++) - 63;
529
+ result |= (byte & 0x1f) << shift;
530
+ shift += 5;
531
+ } while (byte >= 0x20);
532
+
533
+ latitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
534
+
535
+ shift = result = 0;
536
+
537
+ do {
538
+ byte = str.charCodeAt(index++) - 63;
539
+ result |= (byte & 0x1f) << shift;
540
+ shift += 5;
541
+ } while (byte >= 0x20);
542
+
543
+ longitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
544
+
545
+ lat += latitude_change;
546
+ lng += longitude_change;
547
+
548
+ coordinates.push([lat / factor, lng / factor]);
549
+ }
550
+
551
+ return coordinates;
552
+ },
553
+ _decodePolyline: function (routeGeometry) {
554
+ let cs = this.polyline_decode(routeGeometry, 5),
555
+ result = [],
556
+ i;
557
+ const lng = cs.length;
558
+ for (i = lng - 1; i >= 0; i--) {
559
+ result[i] = L.latLng(cs[i]);
560
+ }
561
+
562
+ return result;
555
563
  }
564
+ }
565
+ }
556
566
  </script>
557
567
  <style lang="scss">
558
- @import "~renusify/style/include";
568
+ @import "~renusify/style/include";
559
569
 
560
- .#{$prefix}map-route {
561
- display: flex;
570
+ .#{$prefix}map-route {
571
+ display: flex;
562
572
 
563
- .route-point {
564
- border: 1px solid #cdcaca;
565
- }
573
+ .route-point {
574
+ border: 1px solid #cdcaca;
575
+ }
566
576
 
567
- .route-name {
568
- cursor: pointer;
577
+ .route-name {
578
+ cursor: pointer;
569
579
 
570
- &:hover {
571
- color: var(--color-link);
572
- }
573
- }
580
+ &:hover {
581
+ color: var(--color-link);
574
582
  }
575
- </style>
583
+ }
584
+ }
585
+ </style>