svgmap 2.19.3 → 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/README.md +4 -0
- package/dist/index.cjs +340 -143
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +340 -143
- package/dist/index.js.map +1 -1
- package/dist/svg-map.css +61 -21
- package/dist/svg-map.min.css +1 -1
- package/dist/svg-map.umd.js +340 -143
- package/dist/svg-map.umd.js.map +1 -1
- package/dist/svg-map.umd.min.js +1 -1
- package/dist/svgMap.css +61 -21
- package/dist/svgMap.js +340 -143
- package/dist/svgMap.js.map +1 -1
- package/dist/svgMap.min.css +1 -1
- package/dist/svgMap.min.js +1 -1
- package/package.json +4 -4
- package/src/js/core/svg-map.js +340 -143
- package/src/scss/map.scss +4 -0
- package/src/scss/tooltip.scss +26 -6
package/dist/svg-map.umd.js
CHANGED
|
@@ -2348,6 +2348,15 @@
|
|
|
2348
2348
|
// Set to true to open the link on mobile devices, set to false (default) to show the tooltip
|
|
2349
2349
|
touchLink: false,
|
|
2350
2350
|
|
|
2351
|
+
// When false, disables hover/touch-following tooltips (not the on-map persistent labels; see persistentTooltips)
|
|
2352
|
+
showTooltips: true,
|
|
2353
|
+
|
|
2354
|
+
// 'hover' (default): mouse shows tooltip on enter. 'click': mouse opens tooltip on click; touch/pen unchanged.
|
|
2355
|
+
tooltipTrigger: 'hover',
|
|
2356
|
+
|
|
2357
|
+
// Persistent on-map tooltips: an array of country IDs, or a function (countryID, countryValues) => boolean
|
|
2358
|
+
persistentTooltips: false,
|
|
2359
|
+
|
|
2351
2360
|
// Set to true to show the to show a zoom reset button
|
|
2352
2361
|
showZoomReset: false,
|
|
2353
2362
|
|
|
@@ -2356,6 +2365,10 @@
|
|
|
2356
2365
|
return null;
|
|
2357
2366
|
},
|
|
2358
2367
|
|
|
2368
|
+
// Called on country click (pointer released without dragging). Receives
|
|
2369
|
+
// (countryID, event). Return false to skip opening data.values[*].link.
|
|
2370
|
+
onCountryClick: null,
|
|
2371
|
+
|
|
2359
2372
|
// Country specific options
|
|
2360
2373
|
countries: {
|
|
2361
2374
|
// Western Sahara: Set to false to combine Morocco (MA) and Western Sahara (EH)
|
|
@@ -2395,6 +2408,9 @@
|
|
|
2395
2408
|
// Wrapper element
|
|
2396
2409
|
this.wrapper = document.getElementById(this.options.targetElementID);
|
|
2397
2410
|
this.wrapper.classList.add('svgMap-wrapper');
|
|
2411
|
+
if (typeof this.options.onCountryClick === 'function') {
|
|
2412
|
+
this.wrapper.classList.add('svgMap-country-click-callback');
|
|
2413
|
+
}
|
|
2398
2414
|
|
|
2399
2415
|
// Container element
|
|
2400
2416
|
this.container = document.createElement('div');
|
|
@@ -3086,7 +3102,9 @@
|
|
|
3086
3102
|
|
|
3087
3103
|
createMap() {
|
|
3088
3104
|
// Create the tooltip
|
|
3089
|
-
this.
|
|
3105
|
+
if (this.options.showTooltips) {
|
|
3106
|
+
this.createTooltip();
|
|
3107
|
+
}
|
|
3090
3108
|
|
|
3091
3109
|
// Create map wrappers
|
|
3092
3110
|
this.mapWrapper = this.createElement(
|
|
@@ -3212,6 +3230,103 @@
|
|
|
3212
3230
|
}.bind(this);
|
|
3213
3231
|
|
|
3214
3232
|
// Add map elements
|
|
3233
|
+
var countryElements = [];
|
|
3234
|
+
|
|
3235
|
+
const clearActive = function clearActive() {
|
|
3236
|
+
this.mapImage
|
|
3237
|
+
.querySelectorAll('.svgMap-active')
|
|
3238
|
+
.forEach((el) => el.classList.remove('svgMap-active'));
|
|
3239
|
+
}.bind(this);
|
|
3240
|
+
|
|
3241
|
+
const isClickTooltip =
|
|
3242
|
+
this.options.showTooltips && this.options.tooltipTrigger === 'click';
|
|
3243
|
+
|
|
3244
|
+
const getCountryFromEvent = function (e) {
|
|
3245
|
+
return e.target && e.target.closest
|
|
3246
|
+
? e.target.closest('.svgMap-country')
|
|
3247
|
+
: null;
|
|
3248
|
+
};
|
|
3249
|
+
|
|
3250
|
+
const raiseCountry = function (countryElement, setActive) {
|
|
3251
|
+
if (setActive) {
|
|
3252
|
+
clearActive();
|
|
3253
|
+
}
|
|
3254
|
+
countryElement.parentNode.insertBefore(
|
|
3255
|
+
countryElement,
|
|
3256
|
+
this.persistentTooltipGroup || null
|
|
3257
|
+
);
|
|
3258
|
+
if (setActive) {
|
|
3259
|
+
countryElement.classList.add('svgMap-active');
|
|
3260
|
+
}
|
|
3261
|
+
}.bind(this);
|
|
3262
|
+
|
|
3263
|
+
const showCountryTooltip = function (countryElement, e, setActive) {
|
|
3264
|
+
raiseCountry(countryElement, setActive);
|
|
3265
|
+
this.setTooltipContent(this.getTooltipContent(countryElement.dataset.id));
|
|
3266
|
+
this.showTooltip(e);
|
|
3267
|
+
}.bind(this);
|
|
3268
|
+
|
|
3269
|
+
// Touch only: preview tooltip on finger down without marking country active
|
|
3270
|
+
// (active is set on pointerup so link countries keep two-tap navigation)
|
|
3271
|
+
this.mapImage.addEventListener(
|
|
3272
|
+
'pointerdown',
|
|
3273
|
+
(e) => {
|
|
3274
|
+
if (!this.options.showTooltips || e.pointerType !== 'touch') {
|
|
3275
|
+
return;
|
|
3276
|
+
}
|
|
3277
|
+
|
|
3278
|
+
const countryElement = getCountryFromEvent(e);
|
|
3279
|
+
if (!countryElement) {
|
|
3280
|
+
this.hideTooltip();
|
|
3281
|
+
return;
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
showCountryTooltip(countryElement, e, false);
|
|
3285
|
+
this.moveTooltip(e);
|
|
3286
|
+
},
|
|
3287
|
+
{ passive: true }
|
|
3288
|
+
);
|
|
3289
|
+
|
|
3290
|
+
this.mapImage.addEventListener(
|
|
3291
|
+
'pointercancel',
|
|
3292
|
+
(e) => {
|
|
3293
|
+
if (e.pointerType === 'touch') {
|
|
3294
|
+
this.hideTooltip();
|
|
3295
|
+
}
|
|
3296
|
+
},
|
|
3297
|
+
{ passive: true }
|
|
3298
|
+
);
|
|
3299
|
+
|
|
3300
|
+
// Hover (mouse/pen) and touch drag: raise country + optional floating tooltip
|
|
3301
|
+
this.mapImage.addEventListener(
|
|
3302
|
+
'pointermove',
|
|
3303
|
+
(e) => {
|
|
3304
|
+
const countryElement = getCountryFromEvent(e);
|
|
3305
|
+
if (!countryElement) {
|
|
3306
|
+
clearActive();
|
|
3307
|
+
if (this.options.showTooltips) {
|
|
3308
|
+
this.hideTooltip();
|
|
3309
|
+
}
|
|
3310
|
+
return;
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3313
|
+
const mouseClickMode = e.pointerType === 'mouse' && isClickTooltip;
|
|
3314
|
+
|
|
3315
|
+
// Always raise hovered country (SVG paint order + .svgMap-active stroke)
|
|
3316
|
+
if (!this.options.showTooltips || mouseClickMode) {
|
|
3317
|
+
raiseCountry(countryElement, true);
|
|
3318
|
+
return;
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
showCountryTooltip(countryElement, e, true);
|
|
3322
|
+
|
|
3323
|
+
if (e.pointerType === 'touch') {
|
|
3324
|
+
this.moveTooltip(e);
|
|
3325
|
+
}
|
|
3326
|
+
},
|
|
3327
|
+
{ passive: true }
|
|
3328
|
+
);
|
|
3329
|
+
|
|
3215
3330
|
Object.keys(mapPaths).forEach(
|
|
3216
3331
|
function (countryID) {
|
|
3217
3332
|
var countryData = this.mapPaths[countryID];
|
|
@@ -3229,156 +3344,50 @@
|
|
|
3229
3344
|
'id',
|
|
3230
3345
|
this.id + '-map-country-' + countryID
|
|
3231
3346
|
);
|
|
3232
|
-
countryElement.
|
|
3347
|
+
countryElement.dataset.id = countryID;
|
|
3233
3348
|
countryElement.classList.add('svgMap-country');
|
|
3234
3349
|
|
|
3235
3350
|
this.mapImage.appendChild(countryElement);
|
|
3236
|
-
|
|
3237
|
-
// Add tooltip when touch is used
|
|
3238
|
-
function handlePointerMove(e) {
|
|
3239
|
-
if (e.pointerType === 'touch') return;
|
|
3240
|
-
|
|
3241
|
-
const target = document.elementFromPoint(e.clientX, e.clientY);
|
|
3242
|
-
|
|
3243
|
-
if (
|
|
3244
|
-
!target ||
|
|
3245
|
-
(!target.closest('.svgMap-country') &&
|
|
3246
|
-
!target.closest('.svgMap-tooltip'))
|
|
3247
|
-
) {
|
|
3248
|
-
this.hideTooltip();
|
|
3249
|
-
document
|
|
3250
|
-
.querySelectorAll('.svgMap-active')
|
|
3251
|
-
.forEach(el => el.classList.remove('svgMap-active'));
|
|
3252
|
-
}
|
|
3253
|
-
}
|
|
3254
|
-
|
|
3255
|
-
const handlePointerMoveBound = handlePointerMove.bind(this);
|
|
3256
|
-
|
|
3257
|
-
countryElement.addEventListener(
|
|
3258
|
-
'pointerenter',
|
|
3259
|
-
function (e) {
|
|
3260
|
-
// Only add pointermove listener for non-touch pointers
|
|
3261
|
-
if (e.pointerType !== 'touch') {
|
|
3262
|
-
document.addEventListener(
|
|
3263
|
-
'pointermove',
|
|
3264
|
-
handlePointerMoveBound,
|
|
3265
|
-
{ passive: true }
|
|
3266
|
-
);
|
|
3267
|
-
}
|
|
3268
|
-
|
|
3269
|
-
document
|
|
3270
|
-
.querySelectorAll('.svgMap-active')
|
|
3271
|
-
.forEach(el => el.classList.remove('svgMap-active'));
|
|
3272
|
-
|
|
3273
|
-
countryElement.parentNode.appendChild(countryElement);
|
|
3274
|
-
countryElement.classList.add('svgMap-active');
|
|
3275
|
-
|
|
3276
|
-
const countryID = countryElement.getAttribute('data-id');
|
|
3277
|
-
this.setTooltipContent(this.getTooltipContent(countryID));
|
|
3278
|
-
this.showTooltip(e);
|
|
3279
|
-
|
|
3280
|
-
// For touch, move tooltip to the touch position and keep it there
|
|
3281
|
-
if (e.pointerType === 'touch') {
|
|
3282
|
-
this.moveTooltip(e);
|
|
3283
|
-
}
|
|
3284
|
-
}.bind(this)
|
|
3285
|
-
);
|
|
3286
|
-
|
|
3287
|
-
// Handle touch move - update tooltip position while panning
|
|
3288
|
-
countryElement.addEventListener(
|
|
3289
|
-
'touchmove',
|
|
3290
|
-
function (e) {
|
|
3291
|
-
this.moveTooltip(e);
|
|
3292
|
-
}.bind(this),
|
|
3293
|
-
{ passive: true }
|
|
3294
|
-
);
|
|
3295
|
-
|
|
3296
|
-
// Handle touch end - remove active state and hide tooltip
|
|
3297
|
-
countryElement.addEventListener(
|
|
3298
|
-
'touchend',
|
|
3299
|
-
function (e) {
|
|
3300
|
-
const touch = e.changedTouches[0];
|
|
3301
|
-
const elementAtEnd = document.elementFromPoint(touch.clientX, touch.clientY);
|
|
3302
|
-
|
|
3303
|
-
// Only hide if touch ended outside the country or tooltip
|
|
3304
|
-
if (
|
|
3305
|
-
!elementAtEnd ||
|
|
3306
|
-
(!elementAtEnd.closest('.svgMap-country') &&
|
|
3307
|
-
!elementAtEnd.closest('.svgMap-tooltip'))
|
|
3308
|
-
) {
|
|
3309
|
-
this.hideTooltip();
|
|
3310
|
-
document
|
|
3311
|
-
.querySelectorAll('.svgMap-active')
|
|
3312
|
-
.forEach(el => el.classList.remove('svgMap-active'));
|
|
3313
|
-
}
|
|
3314
|
-
}.bind(this),
|
|
3315
|
-
{ passive: true }
|
|
3316
|
-
);
|
|
3317
|
-
|
|
3318
|
-
// Remove pointermove listener when leaving non-touch pointer
|
|
3319
|
-
countryElement.addEventListener(
|
|
3320
|
-
'pointerleave',
|
|
3321
|
-
function (e) {
|
|
3322
|
-
if (e.pointerType !== 'touch') {
|
|
3323
|
-
document.removeEventListener('pointermove', handlePointerMoveBound);
|
|
3324
|
-
this.hideTooltip();
|
|
3325
|
-
document
|
|
3326
|
-
.querySelectorAll('.svgMap-active')
|
|
3327
|
-
.forEach(el => el.classList.remove('svgMap-active'));
|
|
3328
|
-
}
|
|
3329
|
-
}.bind(this)
|
|
3330
|
-
);
|
|
3331
|
-
|
|
3332
|
-
document.addEventListener(
|
|
3333
|
-
'pointerover',
|
|
3334
|
-
function (e) {
|
|
3335
|
-
if (e.pointerType !== 'touch') return;
|
|
3336
|
-
|
|
3337
|
-
if (
|
|
3338
|
-
e.target.closest('.svgMap-country') ||
|
|
3339
|
-
e.target.closest('.svgMap-tooltip')
|
|
3340
|
-
) {
|
|
3341
|
-
return;
|
|
3342
|
-
}
|
|
3343
|
-
|
|
3344
|
-
this.hideTooltip();
|
|
3345
|
-
document
|
|
3346
|
-
.querySelectorAll('.svgMap-active')
|
|
3347
|
-
.forEach(el => el.classList.remove('svgMap-active'));
|
|
3348
|
-
}.bind(this),
|
|
3349
|
-
{ passive: true }
|
|
3350
|
-
);
|
|
3351
|
+
countryElements.push(countryElement);
|
|
3351
3352
|
|
|
3352
3353
|
if (
|
|
3353
3354
|
this.options.data.values &&
|
|
3354
3355
|
this.options.data.values[countryID] &&
|
|
3355
3356
|
this.options.data.values[countryID]['link']
|
|
3356
3357
|
) {
|
|
3357
|
-
countryElement.
|
|
3358
|
-
'
|
|
3359
|
-
this.options.data.values[countryID]['link']
|
|
3360
|
-
);
|
|
3358
|
+
countryElement.dataset.link =
|
|
3359
|
+
this.options.data.values[countryID]['link'];
|
|
3361
3360
|
if (this.options.data.values[countryID]['linkTarget']) {
|
|
3362
|
-
countryElement.
|
|
3363
|
-
|
|
3364
|
-
this.options.data.values[countryID]['linkTarget']
|
|
3365
|
-
);
|
|
3361
|
+
countryElement.dataset.linkTarget =
|
|
3362
|
+
this.options.data.values[countryID]['linkTarget'];
|
|
3366
3363
|
}
|
|
3367
3364
|
}
|
|
3368
3365
|
}.bind(this)
|
|
3369
3366
|
);
|
|
3370
3367
|
|
|
3368
|
+
var persistent = this.options.persistentTooltips;
|
|
3369
|
+
if (
|
|
3370
|
+
persistent &&
|
|
3371
|
+
(Array.isArray(persistent) || typeof persistent === 'function')
|
|
3372
|
+
) {
|
|
3373
|
+
this.createPersistentTooltips(countryElements);
|
|
3374
|
+
}
|
|
3375
|
+
|
|
3371
3376
|
let pointerStart = null;
|
|
3372
3377
|
let activeCountry = null;
|
|
3373
3378
|
|
|
3374
|
-
this.mapImage.addEventListener(
|
|
3375
|
-
|
|
3376
|
-
|
|
3379
|
+
this.mapImage.addEventListener(
|
|
3380
|
+
'pointerdown',
|
|
3381
|
+
(e) => {
|
|
3382
|
+
// Ignore right click (on desktop it allows inspecting the chart elements without opening the URL)
|
|
3383
|
+
if (e.button !== 0) return;
|
|
3377
3384
|
|
|
3378
|
-
|
|
3379
|
-
|
|
3385
|
+
pointerStart = { x: e.clientX, y: e.clientY };
|
|
3386
|
+
},
|
|
3387
|
+
{ passive: true }
|
|
3388
|
+
);
|
|
3380
3389
|
|
|
3381
|
-
this.mapImage.addEventListener('pointerup', e => {
|
|
3390
|
+
this.mapImage.addEventListener('pointerup', (e) => {
|
|
3382
3391
|
// Ignore right click (on desktop it allows inspecting the chart elements without opening the URL)
|
|
3383
3392
|
if (e.button !== 0) return;
|
|
3384
3393
|
|
|
@@ -3396,33 +3405,121 @@
|
|
|
3396
3405
|
const countryElement = e.target.closest('.svgMap-country');
|
|
3397
3406
|
if (!countryElement) return;
|
|
3398
3407
|
|
|
3399
|
-
const countryID = countryElement.
|
|
3400
|
-
const link = countryElement.
|
|
3401
|
-
const
|
|
3402
|
-
|
|
3403
|
-
|
|
3408
|
+
const countryID = countryElement.dataset.id;
|
|
3409
|
+
const link = countryElement.dataset.link;
|
|
3410
|
+
const linkTarget = countryElement.dataset.linkTarget;
|
|
3411
|
+
const hasCallback = typeof this.options.onCountryClick === 'function';
|
|
3412
|
+
const hasLink = !!link;
|
|
3404
3413
|
const isTouch = e.pointerType === 'touch' || e.pointerType === 'pen';
|
|
3405
3414
|
|
|
3415
|
+
const isClickTooltipMouse = e.pointerType === 'mouse' && isClickTooltip;
|
|
3416
|
+
|
|
3417
|
+
if (!hasLink && !hasCallback && !isClickTooltipMouse) return;
|
|
3418
|
+
|
|
3419
|
+
if (isClickTooltipMouse) {
|
|
3420
|
+
const willNavigate =
|
|
3421
|
+
hasLink && countryElement.classList.contains('svgMap-active');
|
|
3422
|
+
const shouldFireCallback = hasCallback && (!hasLink || willNavigate);
|
|
3423
|
+
|
|
3424
|
+
var callbackResultClick;
|
|
3425
|
+
if (shouldFireCallback) {
|
|
3426
|
+
callbackResultClick = this.options.onCountryClick(countryID, e);
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3429
|
+
if (hasLink) {
|
|
3430
|
+
if (callbackResultClick === false) return;
|
|
3431
|
+
if (countryElement.classList.contains('svgMap-active')) {
|
|
3432
|
+
if (linkTarget) window.open(link, linkTarget);
|
|
3433
|
+
else window.location.href = link;
|
|
3434
|
+
} else {
|
|
3435
|
+
clearActive();
|
|
3436
|
+
countryElement.parentNode.insertBefore(
|
|
3437
|
+
countryElement,
|
|
3438
|
+
this.persistentTooltipGroup || null
|
|
3439
|
+
);
|
|
3440
|
+
countryElement.classList.add('svgMap-active');
|
|
3441
|
+
this.setTooltipContent(this.getTooltipContent(countryID));
|
|
3442
|
+
this.showTooltip(e);
|
|
3443
|
+
}
|
|
3444
|
+
return;
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
if (callbackResultClick === false) return;
|
|
3448
|
+
|
|
3449
|
+
clearActive();
|
|
3450
|
+
countryElement.parentNode.insertBefore(
|
|
3451
|
+
countryElement,
|
|
3452
|
+
this.persistentTooltipGroup || null
|
|
3453
|
+
);
|
|
3454
|
+
countryElement.classList.add('svgMap-active');
|
|
3455
|
+
this.setTooltipContent(this.getTooltipContent(countryID));
|
|
3456
|
+
this.showTooltip(e);
|
|
3457
|
+
return;
|
|
3458
|
+
}
|
|
3459
|
+
|
|
3460
|
+
const willNavigate =
|
|
3461
|
+
hasLink &&
|
|
3462
|
+
(!isTouch || countryElement.classList.contains('svgMap-active'));
|
|
3463
|
+
|
|
3464
|
+
const shouldFireCallback =
|
|
3465
|
+
hasCallback && (!hasLink || !isTouch || willNavigate);
|
|
3466
|
+
|
|
3467
|
+
var callbackResult;
|
|
3468
|
+
if (shouldFireCallback) {
|
|
3469
|
+
callbackResult = this.options.onCountryClick(countryID, e);
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
if (!hasLink) return;
|
|
3473
|
+
|
|
3474
|
+
if (callbackResult === false) return;
|
|
3475
|
+
|
|
3406
3476
|
if (isTouch) {
|
|
3407
3477
|
// Touch: only open if already active
|
|
3408
3478
|
if (countryElement.classList.contains('svgMap-active')) {
|
|
3409
|
-
if (
|
|
3479
|
+
if (linkTarget) window.open(link, linkTarget);
|
|
3410
3480
|
else window.location.href = link;
|
|
3411
3481
|
} else {
|
|
3412
|
-
// first tap shows tooltip
|
|
3482
|
+
// first tap shows tooltip (or opens link immediately if tooltips are off)
|
|
3413
3483
|
if (activeCountry) activeCountry.classList.remove('svgMap-active');
|
|
3414
3484
|
activeCountry = countryElement;
|
|
3415
3485
|
countryElement.classList.add('svgMap-active');
|
|
3416
|
-
|
|
3417
|
-
|
|
3486
|
+
if (this.options.showTooltips) {
|
|
3487
|
+
this.setTooltipContent(this.getTooltipContent(countryID));
|
|
3488
|
+
this.showTooltip(e);
|
|
3489
|
+
} else {
|
|
3490
|
+
if (linkTarget) window.open(link, linkTarget);
|
|
3491
|
+
else window.location.href = link;
|
|
3492
|
+
}
|
|
3418
3493
|
}
|
|
3419
3494
|
} else {
|
|
3420
3495
|
// Desktop: open immediately
|
|
3421
|
-
if (
|
|
3496
|
+
if (linkTarget) window.open(link, linkTarget);
|
|
3422
3497
|
else window.location.href = link;
|
|
3423
3498
|
}
|
|
3424
3499
|
});
|
|
3425
3500
|
|
|
3501
|
+
this._clickTooltipOutsideHandler = function (ev) {
|
|
3502
|
+
if (!this.tooltip || !this.tooltip.classList.contains('svgMap-active')) {
|
|
3503
|
+
return;
|
|
3504
|
+
}
|
|
3505
|
+
var node = ev.target;
|
|
3506
|
+
if (
|
|
3507
|
+
node &&
|
|
3508
|
+
node.closest &&
|
|
3509
|
+
(node.closest('.svgMap-country') || node.closest('.svgMap-tooltip'))
|
|
3510
|
+
) {
|
|
3511
|
+
return;
|
|
3512
|
+
}
|
|
3513
|
+
this.hideTooltip();
|
|
3514
|
+
if (this.mapImage) {
|
|
3515
|
+
this.mapImage
|
|
3516
|
+
.querySelectorAll('.svgMap-country.svgMap-active')
|
|
3517
|
+
.forEach(function (el) {
|
|
3518
|
+
el.classList.remove('svgMap-active');
|
|
3519
|
+
});
|
|
3520
|
+
}
|
|
3521
|
+
}.bind(this);
|
|
3522
|
+
|
|
3426
3523
|
// Expose instance
|
|
3427
3524
|
var me = this;
|
|
3428
3525
|
|
|
@@ -3488,13 +3585,82 @@
|
|
|
3488
3585
|
}
|
|
3489
3586
|
}
|
|
3490
3587
|
|
|
3588
|
+
// Create the persistent tooltips
|
|
3589
|
+
|
|
3590
|
+
createPersistentTooltips(countryElements) {
|
|
3591
|
+
if (this.persistentTooltipGroup) {
|
|
3592
|
+
this.persistentTooltipGroup.remove();
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
this.persistentTooltipGroup = document.createElementNS(
|
|
3596
|
+
'http://www.w3.org/2000/svg',
|
|
3597
|
+
'g'
|
|
3598
|
+
);
|
|
3599
|
+
this.persistentTooltipGroup.classList.add('svgMap-persistent-tooltips');
|
|
3600
|
+
this.mapImage.appendChild(this.persistentTooltipGroup);
|
|
3601
|
+
|
|
3602
|
+
countryElements.forEach(
|
|
3603
|
+
function (countryElement) {
|
|
3604
|
+
var countryID = countryElement.dataset.id;
|
|
3605
|
+
if (!this.shouldShowTooltipOnLoad(countryID)) {
|
|
3606
|
+
return;
|
|
3607
|
+
}
|
|
3608
|
+
|
|
3609
|
+
var boundingBox = countryElement.getBBox();
|
|
3610
|
+
var tooltipPosition = {
|
|
3611
|
+
x: boundingBox.x + boundingBox.width / 2,
|
|
3612
|
+
y: boundingBox.y + boundingBox.height / 2
|
|
3613
|
+
};
|
|
3614
|
+
|
|
3615
|
+
var tooltipObject = document.createElementNS(
|
|
3616
|
+
'http://www.w3.org/2000/svg',
|
|
3617
|
+
'foreignObject'
|
|
3618
|
+
);
|
|
3619
|
+
tooltipObject.setAttribute('x', tooltipPosition.x);
|
|
3620
|
+
tooltipObject.setAttribute('y', tooltipPosition.y);
|
|
3621
|
+
tooltipObject.setAttribute('width', 1);
|
|
3622
|
+
tooltipObject.setAttribute('height', 1);
|
|
3623
|
+
tooltipObject.classList.add('svgMap-persistent-tooltip-wrapper');
|
|
3624
|
+
|
|
3625
|
+
var tooltipElement = this.createElement(
|
|
3626
|
+
'div',
|
|
3627
|
+
'svgMap-persistent-tooltip',
|
|
3628
|
+
tooltipObject
|
|
3629
|
+
);
|
|
3630
|
+
tooltipElement.append(
|
|
3631
|
+
this.getTooltipContent(countryID, tooltipElement)
|
|
3632
|
+
);
|
|
3633
|
+
this.createElement('div', 'svgMap-tooltip-pointer', tooltipElement);
|
|
3634
|
+
|
|
3635
|
+
this.persistentTooltipGroup.appendChild(tooltipObject);
|
|
3636
|
+
}.bind(this)
|
|
3637
|
+
);
|
|
3638
|
+
}
|
|
3639
|
+
|
|
3640
|
+
// Check if a persistent tooltip should be shown on load
|
|
3641
|
+
|
|
3642
|
+
shouldShowTooltipOnLoad(countryID) {
|
|
3643
|
+
var persistent = this.options.persistentTooltips;
|
|
3644
|
+
var countryValues = this.options.data.values[countryID];
|
|
3645
|
+
|
|
3646
|
+
if (Array.isArray(persistent)) {
|
|
3647
|
+
return persistent.indexOf(countryID) !== -1;
|
|
3648
|
+
}
|
|
3649
|
+
|
|
3650
|
+
if (typeof persistent === 'function') {
|
|
3651
|
+
return persistent(countryID, countryValues);
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3654
|
+
return false;
|
|
3655
|
+
}
|
|
3656
|
+
|
|
3491
3657
|
// Create the tooltip content
|
|
3492
3658
|
|
|
3493
|
-
getTooltipContent(countryID) {
|
|
3659
|
+
getTooltipContent(countryID, tooltipDiv = this.tooltip) {
|
|
3494
3660
|
// Custom tooltip
|
|
3495
3661
|
if (this.options.onGetTooltip) {
|
|
3496
3662
|
var customDiv = this.options.onGetTooltip(
|
|
3497
|
-
|
|
3663
|
+
tooltipDiv,
|
|
3498
3664
|
countryID,
|
|
3499
3665
|
this.options.data.values[countryID]
|
|
3500
3666
|
);
|
|
@@ -4476,19 +4642,50 @@
|
|
|
4476
4642
|
// Show the tooltip
|
|
4477
4643
|
|
|
4478
4644
|
showTooltip(e) {
|
|
4645
|
+
if (!this.tooltip) {
|
|
4646
|
+
return;
|
|
4647
|
+
}
|
|
4479
4648
|
this.tooltip.classList.add('svgMap-active');
|
|
4649
|
+
|
|
4650
|
+
if (
|
|
4651
|
+
this.options.showTooltips &&
|
|
4652
|
+
this.options.tooltipTrigger === 'click' &&
|
|
4653
|
+
e.pointerType === 'mouse'
|
|
4654
|
+
) {
|
|
4655
|
+
// don't register event listener in the same frame
|
|
4656
|
+
// to prevent it from being triggered immediately
|
|
4657
|
+
requestAnimationFrame(() => {
|
|
4658
|
+
document.addEventListener(
|
|
4659
|
+
'pointerdown',
|
|
4660
|
+
this._clickTooltipOutsideHandler,
|
|
4661
|
+
{ once: true, passive: true }
|
|
4662
|
+
);
|
|
4663
|
+
});
|
|
4664
|
+
}
|
|
4665
|
+
|
|
4480
4666
|
this.moveTooltip(e);
|
|
4481
4667
|
}
|
|
4482
4668
|
|
|
4483
4669
|
// Hide the tooltip
|
|
4484
4670
|
|
|
4485
4671
|
hideTooltip() {
|
|
4672
|
+
if (!this.tooltip) {
|
|
4673
|
+
return;
|
|
4674
|
+
}
|
|
4675
|
+
|
|
4486
4676
|
this.tooltip.classList.remove('svgMap-active');
|
|
4677
|
+
document.removeEventListener(
|
|
4678
|
+
'pointerdown',
|
|
4679
|
+
this._clickTooltipOutsideHandler
|
|
4680
|
+
);
|
|
4487
4681
|
}
|
|
4488
4682
|
|
|
4489
4683
|
// Move the tooltip
|
|
4490
4684
|
|
|
4491
4685
|
moveTooltip(e) {
|
|
4686
|
+
if (!this.tooltip) {
|
|
4687
|
+
return;
|
|
4688
|
+
}
|
|
4492
4689
|
var x = e.pageX || (e.touches && e.touches[0] ? e.touches[0].pageX : null);
|
|
4493
4690
|
var y = e.pageY || (e.touches && e.touches[0] ? e.touches[0].pageY : null);
|
|
4494
4691
|
|