svgmap 2.19.3 → 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(
@@ -3212,6 +3230,7 @@
3212
3230
  }.bind(this);
3213
3231
 
3214
3232
  // Add map elements
3233
+ var countryElements = [];
3215
3234
  Object.keys(mapPaths).forEach(
3216
3235
  function (countryID) {
3217
3236
  var countryData = this.mapPaths[countryID];
@@ -3233,6 +3252,7 @@
3233
3252
  countryElement.classList.add('svgMap-country');
3234
3253
 
3235
3254
  this.mapImage.appendChild(countryElement);
3255
+ countryElements.push(countryElement);
3236
3256
 
3237
3257
  // Add tooltip when touch is used
3238
3258
  function handlePointerMove(e) {
@@ -3248,7 +3268,7 @@
3248
3268
  this.hideTooltip();
3249
3269
  document
3250
3270
  .querySelectorAll('.svgMap-active')
3251
- .forEach(el => el.classList.remove('svgMap-active'));
3271
+ .forEach((el) => el.classList.remove('svgMap-active'));
3252
3272
  }
3253
3273
  }
3254
3274
 
@@ -3257,29 +3277,40 @@
3257
3277
  countryElement.addEventListener(
3258
3278
  'pointerenter',
3259
3279
  function (e) {
3280
+ if (
3281
+ e.pointerType === 'mouse' &&
3282
+ this.options.showTooltips &&
3283
+ this.options.tooltipTrigger === 'click'
3284
+ ) {
3285
+ return;
3286
+ }
3287
+
3260
3288
  // Only add pointermove listener for non-touch pointers
3261
3289
  if (e.pointerType !== 'touch') {
3262
- document.addEventListener(
3263
- 'pointermove',
3264
- handlePointerMoveBound,
3265
- { passive: true }
3266
- );
3290
+ document.addEventListener('pointermove', handlePointerMoveBound, {
3291
+ passive: true
3292
+ });
3267
3293
  }
3268
3294
 
3269
3295
  document
3270
3296
  .querySelectorAll('.svgMap-active')
3271
- .forEach(el => el.classList.remove('svgMap-active'));
3297
+ .forEach((el) => el.classList.remove('svgMap-active'));
3272
3298
 
3273
- countryElement.parentNode.appendChild(countryElement);
3299
+ countryElement.parentNode.insertBefore(
3300
+ countryElement,
3301
+ this.persistentTooltipGroup || null
3302
+ );
3274
3303
  countryElement.classList.add('svgMap-active');
3275
3304
 
3276
3305
  const countryID = countryElement.getAttribute('data-id');
3277
- this.setTooltipContent(this.getTooltipContent(countryID));
3278
- this.showTooltip(e);
3306
+ if (this.options.showTooltips) {
3307
+ this.setTooltipContent(this.getTooltipContent(countryID));
3308
+ this.showTooltip(e);
3279
3309
 
3280
- // For touch, move tooltip to the touch position and keep it there
3281
- if (e.pointerType === 'touch') {
3282
- 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
+ }
3283
3314
  }
3284
3315
  }.bind(this)
3285
3316
  );
@@ -3298,7 +3329,10 @@
3298
3329
  'touchend',
3299
3330
  function (e) {
3300
3331
  const touch = e.changedTouches[0];
3301
- const elementAtEnd = document.elementFromPoint(touch.clientX, touch.clientY);
3332
+ const elementAtEnd = document.elementFromPoint(
3333
+ touch.clientX,
3334
+ touch.clientY
3335
+ );
3302
3336
 
3303
3337
  // Only hide if touch ended outside the country or tooltip
3304
3338
  if (
@@ -3309,7 +3343,7 @@
3309
3343
  this.hideTooltip();
3310
3344
  document
3311
3345
  .querySelectorAll('.svgMap-active')
3312
- .forEach(el => el.classList.remove('svgMap-active'));
3346
+ .forEach((el) => el.classList.remove('svgMap-active'));
3313
3347
  }
3314
3348
  }.bind(this),
3315
3349
  { passive: true }
@@ -3320,11 +3354,22 @@
3320
3354
  'pointerleave',
3321
3355
  function (e) {
3322
3356
  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'));
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
+ }
3328
3373
  }
3329
3374
  }.bind(this)
3330
3375
  );
@@ -3344,7 +3389,7 @@
3344
3389
  this.hideTooltip();
3345
3390
  document
3346
3391
  .querySelectorAll('.svgMap-active')
3347
- .forEach(el => el.classList.remove('svgMap-active'));
3392
+ .forEach((el) => el.classList.remove('svgMap-active'));
3348
3393
  }.bind(this),
3349
3394
  { passive: true }
3350
3395
  );
@@ -3368,17 +3413,29 @@
3368
3413
  }.bind(this)
3369
3414
  );
3370
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
+
3371
3424
  let pointerStart = null;
3372
3425
  let activeCountry = null;
3373
3426
 
3374
- this.mapImage.addEventListener('pointerdown', e => {
3375
- // Ignore right click (on desktop it allows inspecting the chart elements without opening the URL)
3376
- 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;
3377
3432
 
3378
- pointerStart = { x: e.clientX, y: e.clientY };
3379
- }, { passive: true });
3433
+ pointerStart = { x: e.clientX, y: e.clientY };
3434
+ },
3435
+ { passive: true }
3436
+ );
3380
3437
 
3381
- this.mapImage.addEventListener('pointerup', e => {
3438
+ this.mapImage.addEventListener('pointerup', (e) => {
3382
3439
  // Ignore right click (on desktop it allows inspecting the chart elements without opening the URL)
3383
3440
  if (e.button !== 0) return;
3384
3441
 
@@ -3398,31 +3455,137 @@
3398
3455
 
3399
3456
  const countryID = countryElement.getAttribute('data-id');
3400
3457
  const link = countryElement.getAttribute('data-link');
3401
- const target = countryElement.getAttribute('data-link-target');
3402
- if (!link) return;
3403
-
3458
+ const linkTarget = countryElement.getAttribute('data-link-target');
3459
+ const hasCallback = typeof this.options.onCountryClick === 'function';
3460
+ const hasLink = !!link;
3404
3461
  const isTouch = e.pointerType === 'touch' || e.pointerType === 'pen';
3405
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
+
3406
3531
  if (isTouch) {
3407
3532
  // Touch: only open if already active
3408
3533
  if (countryElement.classList.contains('svgMap-active')) {
3409
- if (target) window.open(link, target);
3534
+ if (linkTarget) window.open(link, linkTarget);
3410
3535
  else window.location.href = link;
3411
3536
  } else {
3412
- // first tap shows tooltip
3537
+ // first tap shows tooltip (or opens link immediately if tooltips are off)
3413
3538
  if (activeCountry) activeCountry.classList.remove('svgMap-active');
3414
3539
  activeCountry = countryElement;
3415
3540
  countryElement.classList.add('svgMap-active');
3416
- this.setTooltipContent(this.getTooltipContent(countryID));
3417
- 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
+ }
3418
3548
  }
3419
3549
  } else {
3420
3550
  // Desktop: open immediately
3421
- if (target) window.open(link, target);
3551
+ if (linkTarget) window.open(link, linkTarget);
3422
3552
  else window.location.href = link;
3423
3553
  }
3424
3554
  });
3425
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
+
3426
3589
  // Expose instance
3427
3590
  var me = this;
3428
3591
 
@@ -3488,13 +3651,82 @@
3488
3651
  }
3489
3652
  }
3490
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
+
3491
3723
  // Create the tooltip content
3492
3724
 
3493
- getTooltipContent(countryID) {
3725
+ getTooltipContent(countryID, tooltipDiv = this.tooltip) {
3494
3726
  // Custom tooltip
3495
3727
  if (this.options.onGetTooltip) {
3496
3728
  var customDiv = this.options.onGetTooltip(
3497
- this.tooltip,
3729
+ tooltipDiv,
3498
3730
  countryID,
3499
3731
  this.options.data.values[countryID]
3500
3732
  );
@@ -4476,6 +4708,9 @@
4476
4708
  // Show the tooltip
4477
4709
 
4478
4710
  showTooltip(e) {
4711
+ if (!this.tooltip) {
4712
+ return;
4713
+ }
4479
4714
  this.tooltip.classList.add('svgMap-active');
4480
4715
  this.moveTooltip(e);
4481
4716
  }
@@ -4483,12 +4718,18 @@
4483
4718
  // Hide the tooltip
4484
4719
 
4485
4720
  hideTooltip() {
4721
+ if (!this.tooltip) {
4722
+ return;
4723
+ }
4486
4724
  this.tooltip.classList.remove('svgMap-active');
4487
4725
  }
4488
4726
 
4489
4727
  // Move the tooltip
4490
4728
 
4491
4729
  moveTooltip(e) {
4730
+ if (!this.tooltip) {
4731
+ return;
4732
+ }
4492
4733
  var x = e.pageX || (e.touches && e.touches[0] ? e.touches[0].pageX : null);
4493
4734
  var y = e.pageY || (e.touches && e.touches[0] ? e.touches[0].pageY : null);
4494
4735