svgmap 2.20.0 → 2.20.1
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/dist/index.cjs +132 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +132 -176
- package/dist/index.js.map +1 -1
- package/dist/svg-map.umd.js +132 -176
- package/dist/svg-map.umd.js.map +1 -1
- package/dist/svg-map.umd.min.js +1 -1
- package/dist/svgMap.js +132 -176
- package/dist/svgMap.js.map +1 -1
- package/dist/svgMap.min.js +1 -1
- package/package.json +4 -4
- package/src/js/core/svg-map.js +132 -176
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svgmap",
|
|
3
3
|
"description": "svgMap is a JavaScript library that lets you easily create an interactable world map comparing customizable data for each country.",
|
|
4
|
-
"version": "2.20.
|
|
4
|
+
"version": "2.20.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
"prepublishOnly": "npm run build && node test/assets.js"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@rollup/plugin-commonjs": "^29.0.
|
|
46
|
+
"@rollup/plugin-commonjs": "^29.0.3",
|
|
47
47
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
48
48
|
"@rollup/plugin-terser": "^1.0.0",
|
|
49
49
|
"csso": "^5.0.5",
|
|
50
|
-
"rollup": "^4.
|
|
50
|
+
"rollup": "^4.61.0",
|
|
51
51
|
"rollup-plugin-postcss": "^4.0.2",
|
|
52
|
-
"sass": "^1.
|
|
52
|
+
"sass": "^1.100.0"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/js/core/svg-map.js
CHANGED
|
@@ -953,6 +953,102 @@ export default class svgMap {
|
|
|
953
953
|
|
|
954
954
|
// Add map elements
|
|
955
955
|
var countryElements = [];
|
|
956
|
+
|
|
957
|
+
const clearActive = function clearActive() {
|
|
958
|
+
this.mapImage
|
|
959
|
+
.querySelectorAll('.svgMap-active')
|
|
960
|
+
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
961
|
+
}.bind(this);
|
|
962
|
+
|
|
963
|
+
const isClickTooltip =
|
|
964
|
+
this.options.showTooltips && this.options.tooltipTrigger === 'click';
|
|
965
|
+
|
|
966
|
+
const getCountryFromEvent = function (e) {
|
|
967
|
+
return e.target && e.target.closest
|
|
968
|
+
? e.target.closest('.svgMap-country')
|
|
969
|
+
: null;
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
const raiseCountry = function (countryElement, setActive) {
|
|
973
|
+
if (setActive) {
|
|
974
|
+
clearActive();
|
|
975
|
+
}
|
|
976
|
+
countryElement.parentNode.insertBefore(
|
|
977
|
+
countryElement,
|
|
978
|
+
this.persistentTooltipGroup || null
|
|
979
|
+
);
|
|
980
|
+
if (setActive) {
|
|
981
|
+
countryElement.classList.add('svgMap-active');
|
|
982
|
+
}
|
|
983
|
+
}.bind(this);
|
|
984
|
+
|
|
985
|
+
const showCountryTooltip = function (countryElement, e, setActive) {
|
|
986
|
+
raiseCountry(countryElement, setActive);
|
|
987
|
+
this.setTooltipContent(this.getTooltipContent(countryElement.dataset.id));
|
|
988
|
+
this.showTooltip(e);
|
|
989
|
+
}.bind(this);
|
|
990
|
+
|
|
991
|
+
// Touch only: preview tooltip on finger down without marking country active
|
|
992
|
+
// (active is set on pointerup so link countries keep two-tap navigation)
|
|
993
|
+
this.mapImage.addEventListener(
|
|
994
|
+
'pointerdown',
|
|
995
|
+
(e) => {
|
|
996
|
+
if (!this.options.showTooltips || e.pointerType !== 'touch') {
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
const countryElement = getCountryFromEvent(e);
|
|
1001
|
+
if (!countryElement) {
|
|
1002
|
+
this.hideTooltip();
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
showCountryTooltip(countryElement, e, false);
|
|
1007
|
+
this.moveTooltip(e);
|
|
1008
|
+
},
|
|
1009
|
+
{ passive: true }
|
|
1010
|
+
);
|
|
1011
|
+
|
|
1012
|
+
this.mapImage.addEventListener(
|
|
1013
|
+
'pointercancel',
|
|
1014
|
+
(e) => {
|
|
1015
|
+
if (e.pointerType === 'touch') {
|
|
1016
|
+
this.hideTooltip();
|
|
1017
|
+
}
|
|
1018
|
+
},
|
|
1019
|
+
{ passive: true }
|
|
1020
|
+
);
|
|
1021
|
+
|
|
1022
|
+
// Hover (mouse/pen) and touch drag: raise country + optional floating tooltip
|
|
1023
|
+
this.mapImage.addEventListener(
|
|
1024
|
+
'pointermove',
|
|
1025
|
+
(e) => {
|
|
1026
|
+
const countryElement = getCountryFromEvent(e);
|
|
1027
|
+
if (!countryElement) {
|
|
1028
|
+
clearActive();
|
|
1029
|
+
if (this.options.showTooltips) {
|
|
1030
|
+
this.hideTooltip();
|
|
1031
|
+
}
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
const mouseClickMode = e.pointerType === 'mouse' && isClickTooltip;
|
|
1036
|
+
|
|
1037
|
+
// Always raise hovered country (SVG paint order + .svgMap-active stroke)
|
|
1038
|
+
if (!this.options.showTooltips || mouseClickMode) {
|
|
1039
|
+
raiseCountry(countryElement, true);
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
showCountryTooltip(countryElement, e, true);
|
|
1044
|
+
|
|
1045
|
+
if (e.pointerType === 'touch') {
|
|
1046
|
+
this.moveTooltip(e);
|
|
1047
|
+
}
|
|
1048
|
+
},
|
|
1049
|
+
{ passive: true }
|
|
1050
|
+
);
|
|
1051
|
+
|
|
956
1052
|
Object.keys(mapPaths).forEach(
|
|
957
1053
|
function (countryID) {
|
|
958
1054
|
var countryData = this.mapPaths[countryID];
|
|
@@ -970,166 +1066,22 @@ export default class svgMap {
|
|
|
970
1066
|
'id',
|
|
971
1067
|
this.id + '-map-country-' + countryID
|
|
972
1068
|
);
|
|
973
|
-
countryElement.
|
|
1069
|
+
countryElement.dataset.id = countryID;
|
|
974
1070
|
countryElement.classList.add('svgMap-country');
|
|
975
1071
|
|
|
976
1072
|
this.mapImage.appendChild(countryElement);
|
|
977
1073
|
countryElements.push(countryElement);
|
|
978
1074
|
|
|
979
|
-
// Add tooltip when touch is used
|
|
980
|
-
function handlePointerMove(e) {
|
|
981
|
-
if (e.pointerType === 'touch') return;
|
|
982
|
-
|
|
983
|
-
const target = document.elementFromPoint(e.clientX, e.clientY);
|
|
984
|
-
|
|
985
|
-
if (
|
|
986
|
-
!target ||
|
|
987
|
-
(!target.closest('.svgMap-country') &&
|
|
988
|
-
!target.closest('.svgMap-tooltip'))
|
|
989
|
-
) {
|
|
990
|
-
this.hideTooltip();
|
|
991
|
-
document
|
|
992
|
-
.querySelectorAll('.svgMap-active')
|
|
993
|
-
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
const handlePointerMoveBound = handlePointerMove.bind(this);
|
|
998
|
-
|
|
999
|
-
countryElement.addEventListener(
|
|
1000
|
-
'pointerenter',
|
|
1001
|
-
function (e) {
|
|
1002
|
-
if (
|
|
1003
|
-
e.pointerType === 'mouse' &&
|
|
1004
|
-
this.options.showTooltips &&
|
|
1005
|
-
this.options.tooltipTrigger === 'click'
|
|
1006
|
-
) {
|
|
1007
|
-
return;
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// Only add pointermove listener for non-touch pointers
|
|
1011
|
-
if (e.pointerType !== 'touch') {
|
|
1012
|
-
document.addEventListener('pointermove', handlePointerMoveBound, {
|
|
1013
|
-
passive: true
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
document
|
|
1018
|
-
.querySelectorAll('.svgMap-active')
|
|
1019
|
-
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
1020
|
-
|
|
1021
|
-
countryElement.parentNode.insertBefore(
|
|
1022
|
-
countryElement,
|
|
1023
|
-
this.persistentTooltipGroup || null
|
|
1024
|
-
);
|
|
1025
|
-
countryElement.classList.add('svgMap-active');
|
|
1026
|
-
|
|
1027
|
-
const countryID = countryElement.getAttribute('data-id');
|
|
1028
|
-
if (this.options.showTooltips) {
|
|
1029
|
-
this.setTooltipContent(this.getTooltipContent(countryID));
|
|
1030
|
-
this.showTooltip(e);
|
|
1031
|
-
|
|
1032
|
-
// For touch, move tooltip to the touch position and keep it there
|
|
1033
|
-
if (e.pointerType === 'touch') {
|
|
1034
|
-
this.moveTooltip(e);
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
}.bind(this)
|
|
1038
|
-
);
|
|
1039
|
-
|
|
1040
|
-
// Handle touch move - update tooltip position while panning
|
|
1041
|
-
countryElement.addEventListener(
|
|
1042
|
-
'touchmove',
|
|
1043
|
-
function (e) {
|
|
1044
|
-
this.moveTooltip(e);
|
|
1045
|
-
}.bind(this),
|
|
1046
|
-
{ passive: true }
|
|
1047
|
-
);
|
|
1048
|
-
|
|
1049
|
-
// Handle touch end - remove active state and hide tooltip
|
|
1050
|
-
countryElement.addEventListener(
|
|
1051
|
-
'touchend',
|
|
1052
|
-
function (e) {
|
|
1053
|
-
const touch = e.changedTouches[0];
|
|
1054
|
-
const elementAtEnd = document.elementFromPoint(
|
|
1055
|
-
touch.clientX,
|
|
1056
|
-
touch.clientY
|
|
1057
|
-
);
|
|
1058
|
-
|
|
1059
|
-
// Only hide if touch ended outside the country or tooltip
|
|
1060
|
-
if (
|
|
1061
|
-
!elementAtEnd ||
|
|
1062
|
-
(!elementAtEnd.closest('.svgMap-country') &&
|
|
1063
|
-
!elementAtEnd.closest('.svgMap-tooltip'))
|
|
1064
|
-
) {
|
|
1065
|
-
this.hideTooltip();
|
|
1066
|
-
document
|
|
1067
|
-
.querySelectorAll('.svgMap-active')
|
|
1068
|
-
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
1069
|
-
}
|
|
1070
|
-
}.bind(this),
|
|
1071
|
-
{ passive: true }
|
|
1072
|
-
);
|
|
1073
|
-
|
|
1074
|
-
// Remove pointermove listener when leaving non-touch pointer
|
|
1075
|
-
countryElement.addEventListener(
|
|
1076
|
-
'pointerleave',
|
|
1077
|
-
function (e) {
|
|
1078
|
-
if (e.pointerType !== 'touch') {
|
|
1079
|
-
document.removeEventListener(
|
|
1080
|
-
'pointermove',
|
|
1081
|
-
handlePointerMoveBound
|
|
1082
|
-
);
|
|
1083
|
-
if (
|
|
1084
|
-
!(
|
|
1085
|
-
e.pointerType === 'mouse' &&
|
|
1086
|
-
this.options.showTooltips &&
|
|
1087
|
-
this.options.tooltipTrigger === 'click'
|
|
1088
|
-
)
|
|
1089
|
-
) {
|
|
1090
|
-
this.hideTooltip();
|
|
1091
|
-
document
|
|
1092
|
-
.querySelectorAll('.svgMap-active')
|
|
1093
|
-
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
}.bind(this)
|
|
1097
|
-
);
|
|
1098
|
-
|
|
1099
|
-
document.addEventListener(
|
|
1100
|
-
'pointerover',
|
|
1101
|
-
function (e) {
|
|
1102
|
-
if (e.pointerType !== 'touch') return;
|
|
1103
|
-
|
|
1104
|
-
if (
|
|
1105
|
-
e.target.closest('.svgMap-country') ||
|
|
1106
|
-
e.target.closest('.svgMap-tooltip')
|
|
1107
|
-
) {
|
|
1108
|
-
return;
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
this.hideTooltip();
|
|
1112
|
-
document
|
|
1113
|
-
.querySelectorAll('.svgMap-active')
|
|
1114
|
-
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
1115
|
-
}.bind(this),
|
|
1116
|
-
{ passive: true }
|
|
1117
|
-
);
|
|
1118
|
-
|
|
1119
1075
|
if (
|
|
1120
1076
|
this.options.data.values &&
|
|
1121
1077
|
this.options.data.values[countryID] &&
|
|
1122
1078
|
this.options.data.values[countryID]['link']
|
|
1123
1079
|
) {
|
|
1124
|
-
countryElement.
|
|
1125
|
-
'
|
|
1126
|
-
this.options.data.values[countryID]['link']
|
|
1127
|
-
);
|
|
1080
|
+
countryElement.dataset.link =
|
|
1081
|
+
this.options.data.values[countryID]['link'];
|
|
1128
1082
|
if (this.options.data.values[countryID]['linkTarget']) {
|
|
1129
|
-
countryElement.
|
|
1130
|
-
|
|
1131
|
-
this.options.data.values[countryID]['linkTarget']
|
|
1132
|
-
);
|
|
1083
|
+
countryElement.dataset.linkTarget =
|
|
1084
|
+
this.options.data.values[countryID]['linkTarget'];
|
|
1133
1085
|
}
|
|
1134
1086
|
}
|
|
1135
1087
|
}.bind(this)
|
|
@@ -1175,21 +1127,18 @@ export default class svgMap {
|
|
|
1175
1127
|
const countryElement = e.target.closest('.svgMap-country');
|
|
1176
1128
|
if (!countryElement) return;
|
|
1177
1129
|
|
|
1178
|
-
const countryID = countryElement.
|
|
1179
|
-
const link = countryElement.
|
|
1180
|
-
const linkTarget = countryElement.
|
|
1130
|
+
const countryID = countryElement.dataset.id;
|
|
1131
|
+
const link = countryElement.dataset.link;
|
|
1132
|
+
const linkTarget = countryElement.dataset.linkTarget;
|
|
1181
1133
|
const hasCallback = typeof this.options.onCountryClick === 'function';
|
|
1182
1134
|
const hasLink = !!link;
|
|
1183
1135
|
const isTouch = e.pointerType === 'touch' || e.pointerType === 'pen';
|
|
1184
1136
|
|
|
1185
|
-
const isClickTooltipMouse =
|
|
1186
|
-
e.pointerType === 'mouse' &&
|
|
1187
|
-
this.options.showTooltips &&
|
|
1188
|
-
this.options.tooltipTrigger === 'click';
|
|
1137
|
+
const isClickTooltipMouse = e.pointerType === 'mouse' && isClickTooltip;
|
|
1189
1138
|
|
|
1190
1139
|
if (!hasLink && !hasCallback && !isClickTooltipMouse) return;
|
|
1191
1140
|
|
|
1192
|
-
if (isClickTooltipMouse
|
|
1141
|
+
if (isClickTooltipMouse) {
|
|
1193
1142
|
const willNavigate =
|
|
1194
1143
|
hasLink && countryElement.classList.contains('svgMap-active');
|
|
1195
1144
|
const shouldFireCallback = hasCallback && (!hasLink || willNavigate);
|
|
@@ -1205,9 +1154,7 @@ export default class svgMap {
|
|
|
1205
1154
|
if (linkTarget) window.open(link, linkTarget);
|
|
1206
1155
|
else window.location.href = link;
|
|
1207
1156
|
} else {
|
|
1208
|
-
|
|
1209
|
-
.querySelectorAll('.svgMap-country.svgMap-active')
|
|
1210
|
-
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
1157
|
+
clearActive();
|
|
1211
1158
|
countryElement.parentNode.insertBefore(
|
|
1212
1159
|
countryElement,
|
|
1213
1160
|
this.persistentTooltipGroup || null
|
|
@@ -1221,9 +1168,7 @@ export default class svgMap {
|
|
|
1221
1168
|
|
|
1222
1169
|
if (callbackResultClick === false) return;
|
|
1223
1170
|
|
|
1224
|
-
|
|
1225
|
-
.querySelectorAll('.svgMap-country.svgMap-active')
|
|
1226
|
-
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
1171
|
+
clearActive();
|
|
1227
1172
|
countryElement.parentNode.insertBefore(
|
|
1228
1173
|
countryElement,
|
|
1229
1174
|
this.persistentTooltipGroup || null
|
|
@@ -1276,15 +1221,9 @@ export default class svgMap {
|
|
|
1276
1221
|
});
|
|
1277
1222
|
|
|
1278
1223
|
this._clickTooltipOutsideHandler = function (ev) {
|
|
1279
|
-
if (
|
|
1280
|
-
if (
|
|
1281
|
-
!this.options.showTooltips ||
|
|
1282
|
-
this.options.tooltipTrigger !== 'click' ||
|
|
1283
|
-
!this.tooltip
|
|
1284
|
-
) {
|
|
1224
|
+
if (!this.tooltip || !this.tooltip.classList.contains('svgMap-active')) {
|
|
1285
1225
|
return;
|
|
1286
1226
|
}
|
|
1287
|
-
if (!this.tooltip.classList.contains('svgMap-active')) return;
|
|
1288
1227
|
var node = ev.target;
|
|
1289
1228
|
if (
|
|
1290
1229
|
node &&
|
|
@@ -1302,11 +1241,6 @@ export default class svgMap {
|
|
|
1302
1241
|
});
|
|
1303
1242
|
}
|
|
1304
1243
|
}.bind(this);
|
|
1305
|
-
document.addEventListener(
|
|
1306
|
-
'pointerdown',
|
|
1307
|
-
this._clickTooltipOutsideHandler,
|
|
1308
|
-
true
|
|
1309
|
-
);
|
|
1310
1244
|
|
|
1311
1245
|
// Expose instance
|
|
1312
1246
|
var me = this;
|
|
@@ -1389,7 +1323,7 @@ export default class svgMap {
|
|
|
1389
1323
|
|
|
1390
1324
|
countryElements.forEach(
|
|
1391
1325
|
function (countryElement) {
|
|
1392
|
-
var countryID = countryElement.
|
|
1326
|
+
var countryID = countryElement.dataset.id;
|
|
1393
1327
|
if (!this.shouldShowTooltipOnLoad(countryID)) {
|
|
1394
1328
|
return;
|
|
1395
1329
|
}
|
|
@@ -2434,6 +2368,23 @@ export default class svgMap {
|
|
|
2434
2368
|
return;
|
|
2435
2369
|
}
|
|
2436
2370
|
this.tooltip.classList.add('svgMap-active');
|
|
2371
|
+
|
|
2372
|
+
if (
|
|
2373
|
+
this.options.showTooltips &&
|
|
2374
|
+
this.options.tooltipTrigger === 'click' &&
|
|
2375
|
+
e.pointerType === 'mouse'
|
|
2376
|
+
) {
|
|
2377
|
+
// don't register event listener in the same frame
|
|
2378
|
+
// to prevent it from being triggered immediately
|
|
2379
|
+
requestAnimationFrame(() => {
|
|
2380
|
+
document.addEventListener(
|
|
2381
|
+
'pointerdown',
|
|
2382
|
+
this._clickTooltipOutsideHandler,
|
|
2383
|
+
{ once: true, passive: true }
|
|
2384
|
+
);
|
|
2385
|
+
});
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2437
2388
|
this.moveTooltip(e);
|
|
2438
2389
|
}
|
|
2439
2390
|
|
|
@@ -2443,7 +2394,12 @@ export default class svgMap {
|
|
|
2443
2394
|
if (!this.tooltip) {
|
|
2444
2395
|
return;
|
|
2445
2396
|
}
|
|
2397
|
+
|
|
2446
2398
|
this.tooltip.classList.remove('svgMap-active');
|
|
2399
|
+
document.removeEventListener(
|
|
2400
|
+
'pointerdown',
|
|
2401
|
+
this._clickTooltipOutsideHandler
|
|
2402
|
+
);
|
|
2447
2403
|
}
|
|
2448
2404
|
|
|
2449
2405
|
// Move the tooltip
|