adt-js-components 1.9.4 → 1.9.6
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/package.json +1 -1
- package/src/Map/index.js +128 -97
- package/src/RedrawSnippet/index.js +5 -1
- package/src/SubmitForm/index.js +12 -0
package/package.json
CHANGED
package/src/Map/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {RouteSetting, defaultRouteSettings} from './route.types.js';
|
|
|
7
7
|
|
|
8
8
|
let siteKey;
|
|
9
9
|
let markerImg;
|
|
10
|
+
const svgCache = new Map();
|
|
10
11
|
const mapInstances = new WeakMap();
|
|
11
12
|
const selectedMarkers = new WeakMap();
|
|
12
13
|
const selectionOrder = new WeakMap();
|
|
@@ -16,6 +17,8 @@ const routeSettingsMap = new WeakMap();
|
|
|
16
17
|
const markersDataMap = new WeakMap();
|
|
17
18
|
const markerClusters = new WeakMap();
|
|
18
19
|
const onSelectionChangeMap = new WeakMap();
|
|
20
|
+
const onBeforeRouteCalculationMap = new WeakMap();
|
|
21
|
+
const onAfterRouteCalculationMap = new WeakMap();
|
|
19
22
|
|
|
20
23
|
const DEPOT_TYPE = {
|
|
21
24
|
START: 'depot-start',
|
|
@@ -40,6 +43,8 @@ async function run(options) {
|
|
|
40
43
|
customMarkers = {},
|
|
41
44
|
showSelectionOrder = false,
|
|
42
45
|
markerInfoCallback = null,
|
|
46
|
+
onBeforeRouteCalculation = null,
|
|
47
|
+
onAfterRouteCalculation = null,
|
|
43
48
|
} = JSON.parse(el.dataset.adtMap);
|
|
44
49
|
|
|
45
50
|
/** @type {RouteSetting} */
|
|
@@ -63,6 +68,8 @@ async function run(options) {
|
|
|
63
68
|
routeSettingsMap.set(map, routeSettings);
|
|
64
69
|
markersDataMap.set(map, markers);
|
|
65
70
|
onSelectionChangeMap.set(map, onSelectionChange);
|
|
71
|
+
onBeforeRouteCalculationMap.set(map, onBeforeRouteCalculation);
|
|
72
|
+
onAfterRouteCalculationMap.set(map, onAfterRouteCalculation);
|
|
66
73
|
|
|
67
74
|
L.tileLayer("https://api.mapy.cz/v1/maptiles/basic/256/{z}/{x}/{y}?apikey=" + siteKey, {
|
|
68
75
|
minZoom: 0,
|
|
@@ -157,9 +164,7 @@ async function run(options) {
|
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
if (routeSettings.enabled) {
|
|
160
|
-
|
|
161
|
-
calculateRoute(map);
|
|
162
|
-
}, 500);
|
|
167
|
+
calculateRoute(map);
|
|
163
168
|
}
|
|
164
169
|
|
|
165
170
|
if (callback) {
|
|
@@ -175,11 +180,10 @@ async function run(options) {
|
|
|
175
180
|
if (mutation.type === "childList") {
|
|
176
181
|
mutation.addedNodes.forEach(node => {
|
|
177
182
|
if (node.nodeType === 1) {
|
|
178
|
-
// Zkontroluj samotný node
|
|
179
183
|
if (node.hasAttribute("data-adt-map")) {
|
|
180
184
|
applyEventHandlers(node);
|
|
181
185
|
}
|
|
182
|
-
|
|
186
|
+
|
|
183
187
|
node.querySelectorAll?.('[data-adt-map]').forEach(el => {
|
|
184
188
|
applyEventHandlers(el);
|
|
185
189
|
});
|
|
@@ -344,9 +348,7 @@ function addMarkers(map, markers, options, selectedOptions, position, selectable
|
|
|
344
348
|
map.addLayer(cluster);
|
|
345
349
|
|
|
346
350
|
if (loadedCount === totalMarkers) {
|
|
347
|
-
|
|
348
|
-
checkAndApplyPreselection(map, markers, showSelectionOrder, onSelectionChange, selectable);
|
|
349
|
-
}, 200);
|
|
351
|
+
checkAndApplyPreselection(map, markers, showSelectionOrder, onSelectionChange, selectable);
|
|
350
352
|
}
|
|
351
353
|
}
|
|
352
354
|
|
|
@@ -371,7 +373,7 @@ function createMarker(marker, options, selectedOptions, cluster = null, selectab
|
|
|
371
373
|
const markers = markerInstances.get(map);
|
|
372
374
|
markers.set(marker.id, mapMarker);
|
|
373
375
|
|
|
374
|
-
mapMarker.on('add', function() {
|
|
376
|
+
mapMarker.on('add', function () {
|
|
375
377
|
const el = mapMarker.getElement();
|
|
376
378
|
if (el) {
|
|
377
379
|
el.style.cursor = 'pointer';
|
|
@@ -512,22 +514,29 @@ async function updateMarkerOrderDisplay(map, marker, orderNumber, isSelected, co
|
|
|
512
514
|
|
|
513
515
|
async function createMarkerIcon(map, iconUrl, orderNumber, color = null) {
|
|
514
516
|
let inlineStyle = null;
|
|
515
|
-
const response = await fetch(iconUrl);
|
|
516
|
-
const svg = await response.text();
|
|
517
517
|
const settings = routeSettingsMap.get(map);
|
|
518
518
|
|
|
519
519
|
if ((settings && settings.enabled) || color) {
|
|
520
520
|
inlineStyle = `--marker-fill: ${color ?? settings.color};`;
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
+
let svg;
|
|
524
|
+
if (svgCache.has(iconUrl)) {
|
|
525
|
+
svg = svgCache.get(iconUrl);
|
|
526
|
+
} else {
|
|
527
|
+
const response = await fetch(iconUrl);
|
|
528
|
+
svg = await response.text();
|
|
529
|
+
svgCache.set(iconUrl, svg);
|
|
530
|
+
}
|
|
531
|
+
|
|
523
532
|
return L.divIcon({
|
|
524
533
|
className: 'marker-icon-wrapper',
|
|
525
534
|
html: `
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
535
|
+
<div class="marker-icon" style="${inlineStyle}">
|
|
536
|
+
${svg}
|
|
537
|
+
${orderNumber ? `<span class="selection-order-label">${orderNumber}</span>` : ''}
|
|
538
|
+
</div>
|
|
539
|
+
`,
|
|
531
540
|
iconSize: [43, 58],
|
|
532
541
|
iconAnchor: [21, 58]
|
|
533
542
|
});
|
|
@@ -584,65 +593,58 @@ async function calculateRoute(map) {
|
|
|
584
593
|
const hasCustomStart = routeSettings.startPoint !== null && routeSettings.startPoint !== undefined;
|
|
585
594
|
const hasCustomEnd = routeSettings.endPoint !== null && routeSettings.endPoint !== undefined;
|
|
586
595
|
|
|
587
|
-
if (hasCustomStart)
|
|
588
|
-
|
|
589
|
-
}
|
|
590
|
-
if (hasCustomEnd) {
|
|
591
|
-
addDepotMarker(map, routeSettings.endPoint, DEPOT_TYPE.END);
|
|
592
|
-
}
|
|
596
|
+
if (hasCustomStart) addDepotMarker(map, routeSettings.startPoint, DEPOT_TYPE.START);
|
|
597
|
+
if (hasCustomEnd) addDepotMarker(map, routeSettings.endPoint, DEPOT_TYPE.END);
|
|
593
598
|
|
|
594
|
-
if (selectedSet
|
|
595
|
-
const orderedIds = Array.from(order.entries())
|
|
596
|
-
.sort((a, b) => a[1] - b[1])
|
|
597
|
-
.map(entry => entry[0]);
|
|
598
|
-
const routeMarkers = orderedIds
|
|
599
|
-
.map(id => markers.find(m => m.id === id))
|
|
600
|
-
.filter(m => m !== undefined);
|
|
599
|
+
if (!selectedSet || selectedSet.size === 0) return;
|
|
601
600
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
601
|
+
const orderedIds = Array.from(order.entries())
|
|
602
|
+
.sort((a, b) => a[1] - b[1])
|
|
603
|
+
.map(entry => entry[0]);
|
|
604
|
+
const routeMarkers = orderedIds
|
|
605
|
+
.map(id => markers.find(m => m.id === id))
|
|
606
|
+
.filter(m => m !== undefined);
|
|
605
607
|
|
|
606
|
-
|
|
607
|
-
if (hasCustomStart) {
|
|
608
|
-
startPoint = routeSettings.startPoint;
|
|
609
|
-
}
|
|
608
|
+
if (routeMarkers.length < 2) return;
|
|
610
609
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
610
|
+
const beforeCallback = onBeforeRouteCalculationMap.get(map);
|
|
611
|
+
if (beforeCallback && window[beforeCallback]) {
|
|
612
|
+
window[beforeCallback]();
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
let startPoint = hasCustomStart ? routeSettings.startPoint : routeMarkers[0].position;
|
|
616
|
+
let endPoint = hasCustomEnd ? routeSettings.endPoint : routeMarkers[routeMarkers.length - 1].position;
|
|
615
617
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
618
|
+
const WAYPOINTS_LIMIT = 15;
|
|
619
|
+
const allCoords = [];
|
|
620
|
+
const allParts = [];
|
|
621
|
+
let totalDuration = 0;
|
|
622
|
+
let totalLength = 0;
|
|
619
623
|
|
|
624
|
+
try {
|
|
620
625
|
if (routeMarkers.length <= WAYPOINTS_LIMIT) {
|
|
621
|
-
// Pokud je markerů méně nebo rovno 15, použijeme původní logiku
|
|
622
626
|
const params = new URLSearchParams({
|
|
623
627
|
start: `${startPoint.lon},${startPoint.lat}`,
|
|
624
628
|
end: `${endPoint.lon},${endPoint.lat}`,
|
|
625
629
|
routeType: routeSettings.routeType,
|
|
626
630
|
apikey: siteKey
|
|
627
631
|
});
|
|
632
|
+
routeMarkers.forEach(m => params.append('waypoints', `${m.position.lon},${m.position.lat}`));
|
|
628
633
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
try {
|
|
634
|
-
const response = await fetch(
|
|
635
|
-
`https://api.mapy.cz/v1/routing/route?${params.toString()}`
|
|
636
|
-
);
|
|
637
|
-
const data = await response.json();
|
|
634
|
+
const response = await fetch(`https://api.mapy.cz/v1/routing/route?${params.toString()}`);
|
|
635
|
+
const data = await response.json();
|
|
638
636
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
637
|
+
if (data.geometry?.geometry?.coordinates) {
|
|
638
|
+
allCoords.push(...data.geometry.geometry.coordinates.map(c => [c[1], c[0]]));
|
|
639
|
+
}
|
|
640
|
+
if (data.parts) {
|
|
641
|
+
allParts.push(...data.parts);
|
|
642
|
+
}
|
|
643
|
+
if (data.duration) {
|
|
644
|
+
totalDuration += data.duration;
|
|
645
|
+
}
|
|
646
|
+
if (data.length) {
|
|
647
|
+
totalLength += data.length;
|
|
646
648
|
}
|
|
647
649
|
} else {
|
|
648
650
|
const chunks = [];
|
|
@@ -655,18 +657,8 @@ async function calculateRoute(map) {
|
|
|
655
657
|
const isFirstChunk = i === 0;
|
|
656
658
|
const isLastChunk = i === chunks.length - 1;
|
|
657
659
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
if (isFirstChunk) {
|
|
661
|
-
chunkStart = startPoint; // Použije custom start nebo první marker
|
|
662
|
-
chunkEnd = isLastChunk ? endPoint : chunk[chunk.length - 1].position;
|
|
663
|
-
} else if (isLastChunk) {
|
|
664
|
-
chunkStart = chunks[i - 1][chunks[i - 1].length - 1].position;
|
|
665
|
-
chunkEnd = endPoint; // Použije custom end nebo poslední marker
|
|
666
|
-
} else {
|
|
667
|
-
chunkStart = chunks[i - 1][chunks[i - 1].length - 1].position;
|
|
668
|
-
chunkEnd = chunk[chunk.length - 1].position;
|
|
669
|
-
}
|
|
660
|
+
const chunkStart = isFirstChunk ? startPoint : chunks[i - 1][chunks[i - 1].length - 1].position;
|
|
661
|
+
const chunkEnd = isLastChunk ? endPoint : chunk[chunk.length - 1].position;
|
|
670
662
|
|
|
671
663
|
const params = new URLSearchParams({
|
|
672
664
|
start: `${chunkStart.lon},${chunkStart.lat}`,
|
|
@@ -676,38 +668,56 @@ async function calculateRoute(map) {
|
|
|
676
668
|
});
|
|
677
669
|
|
|
678
670
|
const markersToAdd = isFirstChunk ? chunk : chunk.slice(1);
|
|
671
|
+
markersToAdd.forEach(m => params.append('waypoints', `${m.position.lon},${m.position.lat}`));
|
|
679
672
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
});
|
|
683
|
-
|
|
684
|
-
try {
|
|
685
|
-
const response = await fetch(
|
|
686
|
-
`https://api.mapy.cz/v1/routing/route?${params.toString()}`
|
|
687
|
-
);
|
|
688
|
-
const data = await response.json();
|
|
673
|
+
const response = await fetch(`https://api.mapy.cz/v1/routing/route?${params.toString()}`);
|
|
674
|
+
const data = await response.json();
|
|
689
675
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
676
|
+
if (data.geometry?.geometry?.coordinates) {
|
|
677
|
+
allCoords.push(...data.geometry.geometry.coordinates.map(c => [c[1], c[0]]));
|
|
678
|
+
}
|
|
679
|
+
if (data.parts) {
|
|
680
|
+
allParts.push(...data.parts);
|
|
681
|
+
}
|
|
682
|
+
if (data.duration) {
|
|
683
|
+
totalDuration += data.duration;
|
|
684
|
+
}
|
|
685
|
+
if (data.length) {
|
|
686
|
+
totalLength += data.length;
|
|
697
687
|
}
|
|
698
688
|
}
|
|
699
689
|
}
|
|
690
|
+
} catch (error) {
|
|
691
|
+
console.error('Error calculating route:', error);
|
|
692
|
+
const afterCallback = onAfterRouteCalculationMap.get(map);
|
|
693
|
+
if (afterCallback && window[afterCallback]) window[afterCallback]({}, 0, 0);
|
|
700
694
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
color: routeSettings.color,
|
|
704
|
-
weight: routeSettings.weight,
|
|
705
|
-
opacity: routeSettings.opacity
|
|
706
|
-
}).addTo(map);
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
707
697
|
|
|
708
|
-
|
|
709
|
-
|
|
698
|
+
if (allCoords.length > 0) {
|
|
699
|
+
const polyline = L.polyline(allCoords, {
|
|
700
|
+
color: routeSettings.color,
|
|
701
|
+
weight: routeSettings.weight,
|
|
702
|
+
opacity: routeSettings.opacity
|
|
703
|
+
}).addTo(map);
|
|
704
|
+
routePolylines.set(map, polyline);
|
|
710
705
|
}
|
|
706
|
+
|
|
707
|
+
// @type {TRouteParts}
|
|
708
|
+
const routeParts = {};
|
|
709
|
+
allParts.forEach((part, index) => {
|
|
710
|
+
if (index < orderedIds.length) {
|
|
711
|
+
const markerId = orderedIds[index];
|
|
712
|
+
routeParts[markerId] = {
|
|
713
|
+
duration: part.duration,
|
|
714
|
+
length: part.length,
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
const afterCallback = onAfterRouteCalculationMap.get(map);
|
|
720
|
+
if (afterCallback && window[afterCallback]) window[afterCallback](routeParts, totalLength, totalDuration);
|
|
711
721
|
}
|
|
712
722
|
|
|
713
723
|
function addDepotMarker(map, position, depotType) {
|
|
@@ -724,7 +734,7 @@ function addDepotMarker(map, position, depotType) {
|
|
|
724
734
|
iconAnchor: [img.width / 2, img.height]
|
|
725
735
|
});
|
|
726
736
|
|
|
727
|
-
L.marker(position, {
|
|
737
|
+
L.marker(position, {icon: icon}).addTo(map);
|
|
728
738
|
};
|
|
729
739
|
}
|
|
730
740
|
|
|
@@ -805,10 +815,31 @@ function setOrder(mapElement, markerId, orderNumber) {
|
|
|
805
815
|
updateMarkerOrderDisplay(mapElement, marker, orderNumber, true, color);
|
|
806
816
|
}
|
|
807
817
|
|
|
818
|
+
function onBeforeRouteCalculation(mapElement, callbackName) {
|
|
819
|
+
const map = mapInstances.get(mapElement);
|
|
820
|
+
if (!map) return;
|
|
821
|
+
onBeforeRouteCalculationMap.set(map, callbackName);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
function onAfterRouteCalculation(mapElement, callbackName) {
|
|
825
|
+
const map = mapInstances.get(mapElement);
|
|
826
|
+
if (!map) return;
|
|
827
|
+
onAfterRouteCalculationMap.set(map, callbackName);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
function recalculateRoute(mapElement) {
|
|
831
|
+
const map = mapInstances.get(mapElement);
|
|
832
|
+
if (!map) return;
|
|
833
|
+
calculateRoute(map);
|
|
834
|
+
}
|
|
835
|
+
|
|
808
836
|
export default {
|
|
809
837
|
run,
|
|
810
838
|
getSelectedMarkers,
|
|
811
839
|
clearSelection,
|
|
812
840
|
toggleMarker,
|
|
813
841
|
setOrder,
|
|
842
|
+
onBeforeRouteCalculation,
|
|
843
|
+
onAfterRouteCalculation,
|
|
844
|
+
recalculateRoute,
|
|
814
845
|
}
|
|
@@ -4,7 +4,11 @@ async function run(options) {
|
|
|
4
4
|
if ($el.is('button, input[type="button"], input[type="submit"]')) {
|
|
5
5
|
$el.on('click', sendNetteAjax);
|
|
6
6
|
} else if ($el.is('input:not([type="button"]):not([type="submit"]), select, textarea')) {
|
|
7
|
-
|
|
7
|
+
let debounceTimer;
|
|
8
|
+
$el.on('input', function(e) {
|
|
9
|
+
clearTimeout(debounceTimer);
|
|
10
|
+
debounceTimer = setTimeout(() => sendNetteAjax(e), 500);
|
|
11
|
+
});
|
|
8
12
|
}
|
|
9
13
|
}
|
|
10
14
|
|
package/src/SubmitForm/index.js
CHANGED
|
@@ -110,6 +110,14 @@ function run(options) {
|
|
|
110
110
|
|
|
111
111
|
$.nette.ext("submitForm", {
|
|
112
112
|
before: function (xhr, settings) {
|
|
113
|
+
if (settings.nette && settings.nette.el) {
|
|
114
|
+
const pendingXhr = settings.nette.el.data('pendingXhr');
|
|
115
|
+
if (pendingXhr) {
|
|
116
|
+
pendingXhr.abort();
|
|
117
|
+
}
|
|
118
|
+
settings.nette.el.data('pendingXhr', xhr);
|
|
119
|
+
}
|
|
120
|
+
|
|
113
121
|
if (settings.nette && settings.nette.form && settings.nette.form.attr('data-adt-submit-form') !== undefined) {
|
|
114
122
|
let beforeCallback = settings.nette.el.attr('data-adt-submit-form-before-callback');
|
|
115
123
|
if (beforeCallback) {
|
|
@@ -156,6 +164,10 @@ function run(options) {
|
|
|
156
164
|
}
|
|
157
165
|
},
|
|
158
166
|
complete: function (xhr, status, settings) {
|
|
167
|
+
if (settings.nette && settings.nette.el) {
|
|
168
|
+
settings.nette.el.data('pendingXhr', null);
|
|
169
|
+
}
|
|
170
|
+
|
|
159
171
|
// if there are errors we will scroll to first of them
|
|
160
172
|
if (settings.nette && settings.nette.form && settings.nette.form.attr('data-adt-submit-form') !== undefined && settings.nette.form.find('.alert-danger, .is-invalid').length > 0) {
|
|
161
173
|
scrollToFirstError(settings.nette.form);
|