svgmap 2.19.2 → 2.20.0

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/svgMap.css CHANGED
@@ -200,7 +200,12 @@
200
200
  stroke-width: 1.5;
201
201
  }
202
202
 
203
- .svgMap-tooltip {
203
+ .svgMap-wrapper.svgMap-country-click-callback .svgMap-map-wrapper .svgMap-country {
204
+ cursor: pointer;
205
+ }
206
+
207
+ .svgMap-tooltip,
208
+ .svgMap-persistent-tooltip {
204
209
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
205
210
  position: absolute;
206
211
  z-index: 2;
@@ -208,32 +213,33 @@
208
213
  background: #fff;
209
214
  transform: translate(-50%, -100%);
210
215
  border-bottom: 1px solid #111;
211
- display: none;
212
216
  pointer-events: none;
213
217
  min-width: 60px;
214
218
  }
215
- .svgMap-tooltip.svgMap-tooltip-flipped {
219
+ .svgMap-tooltip.svgMap-tooltip-flipped,
220
+ .svgMap-persistent-tooltip.svgMap-tooltip-flipped {
216
221
  transform: translate(-50%, 0);
217
222
  border-bottom: 0;
218
223
  border-top: 1px solid #111;
219
224
  }
220
- .svgMap-tooltip.svgMap-active {
221
- display: block;
222
- }
223
- .svgMap-tooltip .svgMap-tooltip-content-container {
225
+ .svgMap-tooltip .svgMap-tooltip-content-container,
226
+ .svgMap-persistent-tooltip .svgMap-tooltip-content-container {
224
227
  position: relative;
225
228
  padding: 10px 20px;
226
229
  }
227
- .svgMap-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container {
230
+ .svgMap-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container,
231
+ .svgMap-persistent-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container {
228
232
  text-align: center;
229
233
  margin: 2px 0 5px;
230
234
  }
231
- .svgMap-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container.svgMap-tooltip-flag-container-emoji {
235
+ .svgMap-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container.svgMap-tooltip-flag-container-emoji,
236
+ .svgMap-persistent-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container.svgMap-tooltip-flag-container-emoji {
232
237
  font-size: 50px;
233
238
  line-height: 0;
234
239
  padding: 25px 0 15px;
235
240
  }
236
- .svgMap-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container .svgMap-tooltip-flag {
241
+ .svgMap-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container .svgMap-tooltip-flag,
242
+ .svgMap-persistent-tooltip .svgMap-tooltip-content-container .svgMap-tooltip-flag-container .svgMap-tooltip-flag {
237
243
  display: block;
238
244
  margin: auto;
239
245
  width: auto;
@@ -242,47 +248,56 @@
242
248
  background: rgba(0, 0, 0, 0.15);
243
249
  border-radius: 2px;
244
250
  }
245
- .svgMap-tooltip .svgMap-tooltip-title {
251
+ .svgMap-tooltip .svgMap-tooltip-title,
252
+ .svgMap-persistent-tooltip .svgMap-tooltip-title {
246
253
  white-space: nowrap;
247
254
  font-size: 18px;
248
255
  line-height: 28px;
249
256
  padding: 0 0 8px;
250
257
  text-align: center;
251
258
  }
252
- .svgMap-tooltip .svgMap-tooltip-content {
259
+ .svgMap-tooltip .svgMap-tooltip-content,
260
+ .svgMap-persistent-tooltip .svgMap-tooltip-content {
253
261
  white-space: nowrap;
254
262
  text-align: center;
255
263
  font-size: 14px;
256
264
  color: #777;
257
265
  margin: -5px 0 0;
258
266
  }
259
- .svgMap-tooltip .svgMap-tooltip-content table {
267
+ .svgMap-tooltip .svgMap-tooltip-content table,
268
+ .svgMap-persistent-tooltip .svgMap-tooltip-content table {
260
269
  padding: 0;
261
270
  border-spacing: 0px;
262
271
  margin: auto;
263
272
  }
264
- .svgMap-tooltip .svgMap-tooltip-content table td {
273
+ .svgMap-tooltip .svgMap-tooltip-content table td,
274
+ .svgMap-persistent-tooltip .svgMap-tooltip-content table td {
265
275
  padding: 2px 0;
266
276
  text-align: left;
267
277
  }
268
- .svgMap-tooltip .svgMap-tooltip-content table td span {
278
+ .svgMap-tooltip .svgMap-tooltip-content table td span,
279
+ .svgMap-persistent-tooltip .svgMap-tooltip-content table td span {
269
280
  color: #111;
270
281
  }
271
- .svgMap-tooltip .svgMap-tooltip-content table td:first-child {
282
+ .svgMap-tooltip .svgMap-tooltip-content table td:first-child,
283
+ .svgMap-persistent-tooltip .svgMap-tooltip-content table td:first-child {
272
284
  padding-right: 10px;
273
285
  text-align: right;
274
286
  }
275
- .svgMap-tooltip .svgMap-tooltip-content table td sup {
287
+ .svgMap-tooltip .svgMap-tooltip-content table td sup,
288
+ .svgMap-persistent-tooltip .svgMap-tooltip-content table td sup {
276
289
  vertical-align: baseline;
277
290
  position: relative;
278
291
  top: -5px;
279
292
  }
280
- .svgMap-tooltip .svgMap-tooltip-content .svgMap-tooltip-no-data {
293
+ .svgMap-tooltip .svgMap-tooltip-content .svgMap-tooltip-no-data,
294
+ .svgMap-persistent-tooltip .svgMap-tooltip-content .svgMap-tooltip-no-data {
281
295
  padding: 2px 0;
282
296
  color: #777;
283
297
  font-style: italic;
284
298
  }
285
- .svgMap-tooltip .svgMap-tooltip-pointer {
299
+ .svgMap-tooltip .svgMap-tooltip-pointer,
300
+ .svgMap-persistent-tooltip .svgMap-tooltip-pointer {
286
301
  position: absolute;
287
302
  top: 100%;
288
303
  left: 50%;
@@ -291,7 +306,8 @@
291
306
  height: 10px;
292
307
  width: 30px;
293
308
  }
294
- .svgMap-tooltip .svgMap-tooltip-pointer::after {
309
+ .svgMap-tooltip .svgMap-tooltip-pointer::after,
310
+ .svgMap-persistent-tooltip .svgMap-tooltip-pointer::after {
295
311
  content: "";
296
312
  width: 20px;
297
313
  height: 20px;
@@ -302,8 +318,32 @@
302
318
  left: 50%;
303
319
  transform: translateX(-50%) rotate(45deg);
304
320
  }
305
- .svgMap-tooltip.svgMap-tooltip-flipped .svgMap-tooltip-pointer {
321
+ .svgMap-tooltip.svgMap-tooltip-flipped .svgMap-tooltip-pointer,
322
+ .svgMap-persistent-tooltip.svgMap-tooltip-flipped .svgMap-tooltip-pointer {
306
323
  bottom: auto;
307
324
  top: -10px;
308
325
  transform: translateX(-50%) scaleY(-1);
326
+ }
327
+
328
+ .svgMap-tooltip {
329
+ display: none;
330
+ }
331
+ .svgMap-tooltip.svgMap-active {
332
+ display: block;
333
+ }
334
+
335
+ .svgMap-persistent-tooltips,
336
+ .svgMap-persistent-tooltip-wrapper {
337
+ pointer-events: none;
338
+ }
339
+
340
+ .svgMap-persistent-tooltip-wrapper {
341
+ overflow: visible;
342
+ }
343
+
344
+ .svgMap-persistent-tooltip {
345
+ display: block;
346
+ left: 0;
347
+ top: 0;
348
+ width: max-content;
309
349
  }
package/dist/svgMap.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.createTooltip();
3105
+ if (this.options.showTooltips) {
3106
+ this.createTooltip();
3107
+ }
3090
3108
 
3091
3109
  // Create map wrappers
3092
3110
  this.mapWrapper = this.createElement(
@@ -3094,6 +3112,10 @@
3094
3112
  'svgMap-map-wrapper',
3095
3113
  this.mapContainer
3096
3114
  );
3115
+ this.mapWrapper.style.setProperty(
3116
+ '--svg-map-country-fill',
3117
+ this.toHex(this.options.colorNoData)
3118
+ );
3097
3119
  this.mapImage = document.createElementNS(
3098
3120
  'http://www.w3.org/2000/svg',
3099
3121
  'svg'
@@ -3208,6 +3230,7 @@
3208
3230
  }.bind(this);
3209
3231
 
3210
3232
  // Add map elements
3233
+ var countryElements = [];
3211
3234
  Object.keys(mapPaths).forEach(
3212
3235
  function (countryID) {
3213
3236
  var countryData = this.mapPaths[countryID];
@@ -3229,6 +3252,7 @@
3229
3252
  countryElement.classList.add('svgMap-country');
3230
3253
 
3231
3254
  this.mapImage.appendChild(countryElement);
3255
+ countryElements.push(countryElement);
3232
3256
 
3233
3257
  // Add tooltip when touch is used
3234
3258
  function handlePointerMove(e) {
@@ -3244,7 +3268,7 @@
3244
3268
  this.hideTooltip();
3245
3269
  document
3246
3270
  .querySelectorAll('.svgMap-active')
3247
- .forEach(el => el.classList.remove('svgMap-active'));
3271
+ .forEach((el) => el.classList.remove('svgMap-active'));
3248
3272
  }
3249
3273
  }
3250
3274
 
@@ -3253,29 +3277,40 @@
3253
3277
  countryElement.addEventListener(
3254
3278
  'pointerenter',
3255
3279
  function (e) {
3280
+ if (
3281
+ e.pointerType === 'mouse' &&
3282
+ this.options.showTooltips &&
3283
+ this.options.tooltipTrigger === 'click'
3284
+ ) {
3285
+ return;
3286
+ }
3287
+
3256
3288
  // Only add pointermove listener for non-touch pointers
3257
3289
  if (e.pointerType !== 'touch') {
3258
- document.addEventListener(
3259
- 'pointermove',
3260
- handlePointerMoveBound,
3261
- { passive: true }
3262
- );
3290
+ document.addEventListener('pointermove', handlePointerMoveBound, {
3291
+ passive: true
3292
+ });
3263
3293
  }
3264
3294
 
3265
3295
  document
3266
3296
  .querySelectorAll('.svgMap-active')
3267
- .forEach(el => el.classList.remove('svgMap-active'));
3297
+ .forEach((el) => el.classList.remove('svgMap-active'));
3268
3298
 
3269
- countryElement.parentNode.appendChild(countryElement);
3299
+ countryElement.parentNode.insertBefore(
3300
+ countryElement,
3301
+ this.persistentTooltipGroup || null
3302
+ );
3270
3303
  countryElement.classList.add('svgMap-active');
3271
3304
 
3272
3305
  const countryID = countryElement.getAttribute('data-id');
3273
- this.setTooltipContent(this.getTooltipContent(countryID));
3274
- this.showTooltip(e);
3306
+ if (this.options.showTooltips) {
3307
+ this.setTooltipContent(this.getTooltipContent(countryID));
3308
+ this.showTooltip(e);
3275
3309
 
3276
- // For touch, move tooltip to the touch position and keep it there
3277
- if (e.pointerType === 'touch') {
3278
- this.moveTooltip(e);
3310
+ // For touch, move tooltip to the touch position and keep it there
3311
+ if (e.pointerType === 'touch') {
3312
+ this.moveTooltip(e);
3313
+ }
3279
3314
  }
3280
3315
  }.bind(this)
3281
3316
  );
@@ -3294,7 +3329,10 @@
3294
3329
  'touchend',
3295
3330
  function (e) {
3296
3331
  const touch = e.changedTouches[0];
3297
- const elementAtEnd = document.elementFromPoint(touch.clientX, touch.clientY);
3332
+ const elementAtEnd = document.elementFromPoint(
3333
+ touch.clientX,
3334
+ touch.clientY
3335
+ );
3298
3336
 
3299
3337
  // Only hide if touch ended outside the country or tooltip
3300
3338
  if (
@@ -3305,7 +3343,7 @@
3305
3343
  this.hideTooltip();
3306
3344
  document
3307
3345
  .querySelectorAll('.svgMap-active')
3308
- .forEach(el => el.classList.remove('svgMap-active'));
3346
+ .forEach((el) => el.classList.remove('svgMap-active'));
3309
3347
  }
3310
3348
  }.bind(this),
3311
3349
  { passive: true }
@@ -3316,11 +3354,22 @@
3316
3354
  'pointerleave',
3317
3355
  function (e) {
3318
3356
  if (e.pointerType !== 'touch') {
3319
- document.removeEventListener('pointermove', handlePointerMoveBound);
3320
- this.hideTooltip();
3321
- document
3322
- .querySelectorAll('.svgMap-active')
3323
- .forEach(el => el.classList.remove('svgMap-active'));
3357
+ document.removeEventListener(
3358
+ 'pointermove',
3359
+ handlePointerMoveBound
3360
+ );
3361
+ if (
3362
+ !(
3363
+ e.pointerType === 'mouse' &&
3364
+ this.options.showTooltips &&
3365
+ this.options.tooltipTrigger === 'click'
3366
+ )
3367
+ ) {
3368
+ this.hideTooltip();
3369
+ document
3370
+ .querySelectorAll('.svgMap-active')
3371
+ .forEach((el) => el.classList.remove('svgMap-active'));
3372
+ }
3324
3373
  }
3325
3374
  }.bind(this)
3326
3375
  );
@@ -3340,7 +3389,7 @@
3340
3389
  this.hideTooltip();
3341
3390
  document
3342
3391
  .querySelectorAll('.svgMap-active')
3343
- .forEach(el => el.classList.remove('svgMap-active'));
3392
+ .forEach((el) => el.classList.remove('svgMap-active'));
3344
3393
  }.bind(this),
3345
3394
  { passive: true }
3346
3395
  );
@@ -3364,17 +3413,29 @@
3364
3413
  }.bind(this)
3365
3414
  );
3366
3415
 
3416
+ var persistent = this.options.persistentTooltips;
3417
+ if (
3418
+ persistent &&
3419
+ (Array.isArray(persistent) || typeof persistent === 'function')
3420
+ ) {
3421
+ this.createPersistentTooltips(countryElements);
3422
+ }
3423
+
3367
3424
  let pointerStart = null;
3368
3425
  let activeCountry = null;
3369
3426
 
3370
- this.mapImage.addEventListener('pointerdown', e => {
3371
- // Ignore right click (on desktop it allows inspecting the chart elements without opening the URL)
3372
- if (e.button !== 0) return;
3427
+ this.mapImage.addEventListener(
3428
+ 'pointerdown',
3429
+ (e) => {
3430
+ // Ignore right click (on desktop it allows inspecting the chart elements without opening the URL)
3431
+ if (e.button !== 0) return;
3373
3432
 
3374
- pointerStart = { x: e.clientX, y: e.clientY };
3375
- }, { passive: true });
3433
+ pointerStart = { x: e.clientX, y: e.clientY };
3434
+ },
3435
+ { passive: true }
3436
+ );
3376
3437
 
3377
- this.mapImage.addEventListener('pointerup', e => {
3438
+ this.mapImage.addEventListener('pointerup', (e) => {
3378
3439
  // Ignore right click (on desktop it allows inspecting the chart elements without opening the URL)
3379
3440
  if (e.button !== 0) return;
3380
3441
 
@@ -3394,31 +3455,137 @@
3394
3455
 
3395
3456
  const countryID = countryElement.getAttribute('data-id');
3396
3457
  const link = countryElement.getAttribute('data-link');
3397
- const target = countryElement.getAttribute('data-link-target');
3398
- if (!link) return;
3399
-
3458
+ const linkTarget = countryElement.getAttribute('data-link-target');
3459
+ const hasCallback = typeof this.options.onCountryClick === 'function';
3460
+ const hasLink = !!link;
3400
3461
  const isTouch = e.pointerType === 'touch' || e.pointerType === 'pen';
3401
3462
 
3463
+ const isClickTooltipMouse =
3464
+ e.pointerType === 'mouse' &&
3465
+ this.options.showTooltips &&
3466
+ this.options.tooltipTrigger === 'click';
3467
+
3468
+ if (!hasLink && !hasCallback && !isClickTooltipMouse) return;
3469
+
3470
+ if (isClickTooltipMouse && this.options.showTooltips) {
3471
+ const willNavigate =
3472
+ hasLink && countryElement.classList.contains('svgMap-active');
3473
+ const shouldFireCallback = hasCallback && (!hasLink || willNavigate);
3474
+
3475
+ var callbackResultClick;
3476
+ if (shouldFireCallback) {
3477
+ callbackResultClick = this.options.onCountryClick(countryID, e);
3478
+ }
3479
+
3480
+ if (hasLink) {
3481
+ if (callbackResultClick === false) return;
3482
+ if (countryElement.classList.contains('svgMap-active')) {
3483
+ if (linkTarget) window.open(link, linkTarget);
3484
+ else window.location.href = link;
3485
+ } else {
3486
+ this.mapImage
3487
+ .querySelectorAll('.svgMap-country.svgMap-active')
3488
+ .forEach((el) => el.classList.remove('svgMap-active'));
3489
+ countryElement.parentNode.insertBefore(
3490
+ countryElement,
3491
+ this.persistentTooltipGroup || null
3492
+ );
3493
+ countryElement.classList.add('svgMap-active');
3494
+ this.setTooltipContent(this.getTooltipContent(countryID));
3495
+ this.showTooltip(e);
3496
+ }
3497
+ return;
3498
+ }
3499
+
3500
+ if (callbackResultClick === false) return;
3501
+
3502
+ this.mapImage
3503
+ .querySelectorAll('.svgMap-country.svgMap-active')
3504
+ .forEach((el) => el.classList.remove('svgMap-active'));
3505
+ countryElement.parentNode.insertBefore(
3506
+ countryElement,
3507
+ this.persistentTooltipGroup || null
3508
+ );
3509
+ countryElement.classList.add('svgMap-active');
3510
+ this.setTooltipContent(this.getTooltipContent(countryID));
3511
+ this.showTooltip(e);
3512
+ return;
3513
+ }
3514
+
3515
+ const willNavigate =
3516
+ hasLink &&
3517
+ (!isTouch || countryElement.classList.contains('svgMap-active'));
3518
+
3519
+ const shouldFireCallback =
3520
+ hasCallback && (!hasLink || !isTouch || willNavigate);
3521
+
3522
+ var callbackResult;
3523
+ if (shouldFireCallback) {
3524
+ callbackResult = this.options.onCountryClick(countryID, e);
3525
+ }
3526
+
3527
+ if (!hasLink) return;
3528
+
3529
+ if (callbackResult === false) return;
3530
+
3402
3531
  if (isTouch) {
3403
3532
  // Touch: only open if already active
3404
3533
  if (countryElement.classList.contains('svgMap-active')) {
3405
- if (target) window.open(link, target);
3534
+ if (linkTarget) window.open(link, linkTarget);
3406
3535
  else window.location.href = link;
3407
3536
  } else {
3408
- // first tap shows tooltip
3537
+ // first tap shows tooltip (or opens link immediately if tooltips are off)
3409
3538
  if (activeCountry) activeCountry.classList.remove('svgMap-active');
3410
3539
  activeCountry = countryElement;
3411
3540
  countryElement.classList.add('svgMap-active');
3412
- this.setTooltipContent(this.getTooltipContent(countryID));
3413
- this.showTooltip(e);
3541
+ if (this.options.showTooltips) {
3542
+ this.setTooltipContent(this.getTooltipContent(countryID));
3543
+ this.showTooltip(e);
3544
+ } else {
3545
+ if (linkTarget) window.open(link, linkTarget);
3546
+ else window.location.href = link;
3547
+ }
3414
3548
  }
3415
3549
  } else {
3416
3550
  // Desktop: open immediately
3417
- if (target) window.open(link, target);
3551
+ if (linkTarget) window.open(link, linkTarget);
3418
3552
  else window.location.href = link;
3419
3553
  }
3420
3554
  });
3421
3555
 
3556
+ this._clickTooltipOutsideHandler = function (ev) {
3557
+ if (ev.pointerType !== 'mouse') return;
3558
+ if (
3559
+ !this.options.showTooltips ||
3560
+ this.options.tooltipTrigger !== 'click' ||
3561
+ !this.tooltip
3562
+ ) {
3563
+ return;
3564
+ }
3565
+ if (!this.tooltip.classList.contains('svgMap-active')) return;
3566
+ var node = ev.target;
3567
+ if (
3568
+ node &&
3569
+ node.closest &&
3570
+ (node.closest('.svgMap-country') || node.closest('.svgMap-tooltip'))
3571
+ ) {
3572
+ return;
3573
+ }
3574
+ this.hideTooltip();
3575
+ if (this.mapImage) {
3576
+ this.mapImage
3577
+ .querySelectorAll('.svgMap-country.svgMap-active')
3578
+ .forEach(function (el) {
3579
+ el.classList.remove('svgMap-active');
3580
+ });
3581
+ }
3582
+ }.bind(this);
3583
+ document.addEventListener(
3584
+ 'pointerdown',
3585
+ this._clickTooltipOutsideHandler,
3586
+ true
3587
+ );
3588
+
3422
3589
  // Expose instance
3423
3590
  var me = this;
3424
3591
 
@@ -3484,13 +3651,82 @@
3484
3651
  }
3485
3652
  }
3486
3653
 
3654
+ // Create the persistent tooltips
3655
+
3656
+ createPersistentTooltips(countryElements) {
3657
+ if (this.persistentTooltipGroup) {
3658
+ this.persistentTooltipGroup.remove();
3659
+ }
3660
+
3661
+ this.persistentTooltipGroup = document.createElementNS(
3662
+ 'http://www.w3.org/2000/svg',
3663
+ 'g'
3664
+ );
3665
+ this.persistentTooltipGroup.classList.add('svgMap-persistent-tooltips');
3666
+ this.mapImage.appendChild(this.persistentTooltipGroup);
3667
+
3668
+ countryElements.forEach(
3669
+ function (countryElement) {
3670
+ var countryID = countryElement.getAttribute('data-id');
3671
+ if (!this.shouldShowTooltipOnLoad(countryID)) {
3672
+ return;
3673
+ }
3674
+
3675
+ var boundingBox = countryElement.getBBox();
3676
+ var tooltipPosition = {
3677
+ x: boundingBox.x + boundingBox.width / 2,
3678
+ y: boundingBox.y + boundingBox.height / 2
3679
+ };
3680
+
3681
+ var tooltipObject = document.createElementNS(
3682
+ 'http://www.w3.org/2000/svg',
3683
+ 'foreignObject'
3684
+ );
3685
+ tooltipObject.setAttribute('x', tooltipPosition.x);
3686
+ tooltipObject.setAttribute('y', tooltipPosition.y);
3687
+ tooltipObject.setAttribute('width', 1);
3688
+ tooltipObject.setAttribute('height', 1);
3689
+ tooltipObject.classList.add('svgMap-persistent-tooltip-wrapper');
3690
+
3691
+ var tooltipElement = this.createElement(
3692
+ 'div',
3693
+ 'svgMap-persistent-tooltip',
3694
+ tooltipObject
3695
+ );
3696
+ tooltipElement.append(
3697
+ this.getTooltipContent(countryID, tooltipElement)
3698
+ );
3699
+ this.createElement('div', 'svgMap-tooltip-pointer', tooltipElement);
3700
+
3701
+ this.persistentTooltipGroup.appendChild(tooltipObject);
3702
+ }.bind(this)
3703
+ );
3704
+ }
3705
+
3706
+ // Check if a persistent tooltip should be shown on load
3707
+
3708
+ shouldShowTooltipOnLoad(countryID) {
3709
+ var persistent = this.options.persistentTooltips;
3710
+ var countryValues = this.options.data.values[countryID];
3711
+
3712
+ if (Array.isArray(persistent)) {
3713
+ return persistent.indexOf(countryID) !== -1;
3714
+ }
3715
+
3716
+ if (typeof persistent === 'function') {
3717
+ return persistent(countryID, countryValues);
3718
+ }
3719
+
3720
+ return false;
3721
+ }
3722
+
3487
3723
  // Create the tooltip content
3488
3724
 
3489
- getTooltipContent(countryID) {
3725
+ getTooltipContent(countryID, tooltipDiv = this.tooltip) {
3490
3726
  // Custom tooltip
3491
3727
  if (this.options.onGetTooltip) {
3492
3728
  var customDiv = this.options.onGetTooltip(
3493
- this.tooltip,
3729
+ tooltipDiv,
3494
3730
  countryID,
3495
3731
  this.options.data.values[countryID]
3496
3732
  );
@@ -4472,6 +4708,9 @@
4472
4708
  // Show the tooltip
4473
4709
 
4474
4710
  showTooltip(e) {
4711
+ if (!this.tooltip) {
4712
+ return;
4713
+ }
4475
4714
  this.tooltip.classList.add('svgMap-active');
4476
4715
  this.moveTooltip(e);
4477
4716
  }
@@ -4479,12 +4718,18 @@
4479
4718
  // Hide the tooltip
4480
4719
 
4481
4720
  hideTooltip() {
4721
+ if (!this.tooltip) {
4722
+ return;
4723
+ }
4482
4724
  this.tooltip.classList.remove('svgMap-active');
4483
4725
  }
4484
4726
 
4485
4727
  // Move the tooltip
4486
4728
 
4487
4729
  moveTooltip(e) {
4730
+ if (!this.tooltip) {
4731
+ return;
4732
+ }
4488
4733
  var x = e.pageX || (e.touches && e.touches[0] ? e.touches[0].pageX : null);
4489
4734
  var y = e.pageY || (e.touches && e.touches[0] ? e.touches[0].pageY : null);
4490
4735