PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.0.3
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.0.3
9.1.3 9.1.2 9.1.1 9.1.0 9.0.3 9.0.2 9.0.1 9.0.0 8.5.79 8.5.78 8.5.77 8.5.76 8.5.75 8.5.74 8.5.73 8.5.72 8.5.71 8.5.70 8.5.69 8.5.68 8.5.35 8.5.36 8.5.37 8.5.38 8.5.39 All 222 releases
wpvr / legacy / public / js / wpvr-accessibility.js

wpvr-accessibility.js in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 9.0.3, at legacy/public/js/wpvr-accessibility.js

763 lines 25.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function ($) {
2 'use strict';
3
4 var defaults = {
5 tour: 'Virtual tour',
6 instructions: 'Use the arrow keys or W, A, S, and D to look around. Use Tab to reach tour controls and hotspots.',
7 load: 'Load virtual tour',
8 hotspot: 'Tour hotspot',
9 scene: 'View scene',
10 scene_menu: 'Scene menu',
11 previous_scene: 'Previous scene',
12 next_scene: 'Next scene',
13 pan_up: 'Look up',
14 pan_down: 'Look down',
15 pan_left: 'Look left',
16 pan_right: 'Look right',
17 zoom_in: 'Zoom in',
18 zoom_out: 'Zoom out',
19 fullscreen: 'Toggle fullscreen',
20 home: 'Return to starting scene',
21 orientation: 'Toggle device orientation',
22 audio: 'Toggle tour audio',
23 gallery: 'Toggle scene gallery',
24 explainer: 'Open tour video',
25 form: 'Open form',
26 floor_plan: 'Open floor plan',
27 floor_plan_point: 'View scene from floor plan',
28 company_info: 'Company information',
29 close: 'Close dialog',
30 dialog: 'Tour dialog'
31 };
32 var labels = $.extend({}, defaults, window.wpvrAccessibility || {});
33 var dialogSelector = [
34 '.explainer',
35 '.wpvr-generic-form',
36 '.wpvr-floor-map',
37 '.custom-ifram-wrapper',
38 '.wpvr-hotspot-tweak-contents-wrapper'
39 ].join(',');
40 var controlSelector = [
41 '.pnlm-load-button',
42 '.pnlm-zoom-in',
43 '.pnlm-zoom-out',
44 '.pnlm-fullscreen-toggle-button',
45 '.pnlm-orientation-button',
46 '.ctrl',
47 '.explainer_button',
48 '.fullscreen-button',
49 '.vrgcontrols',
50 '.generic_form_button',
51 '.floor_map_button',
52 '.custom-scene-navigation',
53 '.scene-navigation-list',
54 '.floor-plan-pointer',
55 '.scctrl',
56 '.wpvr_owl_prev',
57 '.wpvr_owl_next',
58 '.close-explainer-video',
59 '.close-generic-form',
60 '.close-floor-map-plan',
61 '.cross',
62 '.cp-logo-ctrl'
63 ].join(',');
64 var focusableSelector = [
65 'a[href]',
66 'button:not([disabled])',
67 'input:not([disabled]):not([type="hidden"])',
68 'select:not([disabled])',
69 'textarea:not([disabled])',
70 'iframe',
71 '[tabindex]:not([tabindex="-1"])'
72 ].join(',');
73 var enhancedControls = new WeakSet();
74 var enhancedDialogs = new WeakSet();
75 var externalHotspotLinks = new WeakMap();
76 var dialogStates = new WeakMap();
77 var pendingOpeners = new WeakMap();
78 var movementStates = new WeakMap();
79 var tooltipIndex = 0;
80 var scanQueued = false;
81
82 function isVisible(element) {
83 if (!element || element.hidden) {
84 return false;
85 }
86
87 var current = element;
88 while (current && current.nodeType === 1) {
89 var style = window.getComputedStyle(current);
90 if (style.display === 'none' || style.visibility === 'hidden') {
91 return false;
92 }
93 current = current.parentElement;
94 }
95 return true;
96 }
97
98 function getTour(element) {
99 return element && element.closest ? element.closest('.pano-wrap') : null;
100 }
101
102 function getViewer(container) {
103 if (!container || !window.wpvrViewers) {
104 return null;
105 }
106 return window.wpvrViewers[container.id] || null;
107 }
108
109 function instructionsId(container) {
110 return container.id + '-keyboard-instructions';
111 }
112
113 function enhanceContainer(container) {
114 if (!container.id || container.getAttribute('data-wpvr-a11y') === 'true') {
115 return;
116 }
117
118 container.setAttribute('data-wpvr-a11y', 'true');
119 container.setAttribute('tabindex', '0');
120 container.setAttribute('role', 'region');
121 if (!container.getAttribute('aria-label')) {
122 container.setAttribute('aria-label', labels.tour);
123 }
124
125 var instructions = document.createElement('span');
126 instructions.id = instructionsId(container);
127 instructions.className = 'wpvr-a11y-instructions';
128 instructions.textContent = labels.instructions;
129 container.insertBefore(instructions, container.firstChild);
130 container.setAttribute('aria-describedby', instructions.id);
131 container.addEventListener('keydown', handleViewerKeydown, true);
132 container.addEventListener('keyup', handleViewerKeyup, true);
133 container.addEventListener('blur', stopViewerMovement, true);
134 container.addEventListener('focusin', keepRenderContainerAligned, true);
135 }
136
137 function keepRenderContainerAligned(event) {
138 var viewerContainer = event.currentTarget;
139 var renderContainer = event.target.closest
140 ? event.target.closest('.pnlm-render-container')
141 : null;
142
143 if (!viewerContainer || !renderContainer) {
144 return;
145 }
146
147 function resetScrollPosition() {
148 if (viewerContainer.scrollLeft || viewerContainer.scrollTop) {
149 viewerContainer.scrollLeft = 0;
150 viewerContainer.scrollTop = 0;
151 }
152 if (renderContainer.scrollLeft || renderContainer.scrollTop) {
153 renderContainer.scrollLeft = 0;
154 renderContainer.scrollTop = 0;
155 }
156 }
157
158 resetScrollPosition();
159 window.requestAnimationFrame(resetScrollPosition);
160 window.setTimeout(resetScrollPosition, 0);
161 }
162
163 function handleViewerKeydown(event) {
164 var container = event.currentTarget;
165 if (event.target !== container || event.altKey || event.ctrlKey || event.metaKey) {
166 return;
167 }
168
169 var key = event.key.toLowerCase();
170 var viewer = getViewer(container);
171 var handled = true;
172 var step = event.shiftKey ? 15 : 5;
173
174 if (key === 'enter' || key === ' ') {
175 var loadButton = container.querySelector('.pnlm-load-button');
176 if (loadButton && isVisible(loadButton)) {
177 loadButton.click();
178 focusTourAfterLoad(container);
179 } else {
180 handled = false;
181 }
182 } else if (!viewer) {
183 handled = false;
184 } else if (isMovementKey(key)) {
185 stopAutoRotate(viewer);
186 startViewerMovement(container, key, event.shiftKey);
187 } else if (key === '+' || key === '=') {
188 stopAutoRotate(viewer);
189 viewer.setHfov(viewer.getHfov() - step, false);
190 } else if (key === '-' || key === '_') {
191 stopAutoRotate(viewer);
192 viewer.setHfov(viewer.getHfov() + step, false);
193 } else {
194 handled = false;
195 }
196
197 if (handled) {
198 event.preventDefault();
199 event.stopImmediatePropagation();
200 }
201 }
202
203 function isMovementKey(key) {
204 return key === 'arrowup' || key === 'w' ||
205 key === 'arrowdown' || key === 's' ||
206 key === 'arrowleft' || key === 'a' ||
207 key === 'arrowright' || key === 'd';
208 }
209
210 function movementState(container) {
211 var state = movementStates.get(container);
212 if (!state) {
213 state = {
214 keys: {},
215 fast: false,
216 frame: null,
217 lastFrame: null
218 };
219 movementStates.set(container, state);
220 }
221 return state;
222 }
223
224 function startViewerMovement(container, key, fast) {
225 var state = movementState(container);
226 state.keys[key] = true;
227 state.fast = fast;
228
229 if (state.frame !== null) {
230 return;
231 }
232
233 state.lastFrame = null;
234 state.frame = window.requestAnimationFrame(function move(timestamp) {
235 var viewer = getViewer(container);
236 var current = movementState(container);
237 var moving = Object.keys(current.keys).some(function (pressedKey) {
238 return current.keys[pressedKey];
239 });
240
241 if (!viewer || !moving || document.activeElement !== container) {
242 current.frame = null;
243 current.lastFrame = null;
244 return;
245 }
246
247 if (current.lastFrame === null) {
248 current.lastFrame = timestamp;
249 }
250 var elapsed = Math.min(timestamp - current.lastFrame, 50);
251 var distance = (current.fast ? 90 : 45) * elapsed / 1000;
252 var pitchDirection =
253 (current.keys.arrowup || current.keys.w ? 1 : 0) -
254 (current.keys.arrowdown || current.keys.s ? 1 : 0);
255 var yawDirection =
256 (current.keys.arrowright || current.keys.d ? 1 : 0) -
257 (current.keys.arrowleft || current.keys.a ? 1 : 0);
258
259 current.lastFrame = timestamp;
260 if (pitchDirection) {
261 viewer.setPitch(viewer.getPitch() + pitchDirection * distance, false);
262 }
263 if (yawDirection) {
264 viewer.setYaw(viewer.getYaw() + yawDirection * distance, false);
265 }
266 current.frame = window.requestAnimationFrame(move);
267 });
268 }
269
270 function handleViewerKeyup(event) {
271 var container = event.currentTarget;
272 var key = event.key.toLowerCase();
273 var state = movementStates.get(container);
274
275 if (key === 'shift' && state) {
276 state.fast = false;
277 return;
278 }
279 if (!isMovementKey(key) || !state) {
280 return;
281 }
282
283 state.keys[key] = false;
284 event.preventDefault();
285 event.stopImmediatePropagation();
286 }
287
288 function stopViewerMovement(event) {
289 var container = event.currentTarget || event;
290 var state = movementStates.get(container);
291 if (!state) {
292 return;
293 }
294 state.keys = {};
295 state.lastFrame = null;
296 if (state.frame !== null) {
297 window.cancelAnimationFrame(state.frame);
298 state.frame = null;
299 }
300 }
301
302 function stopAutoRotate(viewer) {
303 if (typeof viewer.stopAutoRotate === 'function') {
304 viewer.stopAutoRotate();
305 }
306 }
307
308 function focusTourAfterLoad(container) {
309 window.setTimeout(function () {
310 container.focus();
311 }, 50);
312 window.setTimeout(function () {
313 if (!container.contains(document.activeElement) || document.activeElement === document.body) {
314 container.focus();
315 }
316 }, 500);
317 }
318
319 function labelFor(element) {
320 var title = element.getAttribute('aria-label') || element.getAttribute('title');
321 if (title) {
322 return title;
323 }
324 if (element.matches('.pnlm-load-button')) {
325 return labels.load;
326 }
327 if (element.matches('.pnlm-zoom-in, [id^="zoom-in"]')) {
328 return labels.zoom_in;
329 }
330 if (element.matches('.pnlm-zoom-out, [id^="zoom-out"]')) {
331 return labels.zoom_out;
332 }
333 if (element.matches('.pnlm-fullscreen-toggle-button, [id^="fullscreen"], .fullscreen-button')) {
334 return labels.fullscreen;
335 }
336 if (element.matches('.pnlm-orientation-button, [id^="gyroscope"]')) {
337 return labels.orientation;
338 }
339 if (element.matches('[id^="pan-up"]')) {
340 return labels.pan_up;
341 }
342 if (element.matches('[id^="pan-down"]')) {
343 return labels.pan_down;
344 }
345 if (element.matches('[id^="pan-left"]')) {
346 return labels.pan_left;
347 }
348 if (element.matches('[id^="pan-right"]')) {
349 return labels.pan_right;
350 }
351 if (element.matches('[id^="backToHome"]')) {
352 return labels.home;
353 }
354 if (element.matches('.audio_control')) {
355 return labels.audio;
356 }
357 if (element.matches('.vrgcontrols')) {
358 return labels.gallery;
359 }
360 if (element.matches('.explainer_button')) {
361 return labels.explainer;
362 }
363 if (element.matches('.generic_form_button')) {
364 return labels.form;
365 }
366 if (element.matches('.floor_map_button')) {
367 return labels.floor_plan;
368 }
369 if (element.matches('.floor-plan-pointer')) {
370 return labels.floor_plan_point;
371 }
372 if (element.matches('.custom-scene-navigation')) {
373 return labels.scene_menu;
374 }
375 if (element.matches('.wpvr_owl_prev')) {
376 return labels.previous_scene;
377 }
378 if (element.matches('.wpvr_owl_next')) {
379 return labels.next_scene;
380 }
381 if (element.matches('.close-explainer-video, .close-generic-form, .close-floor-map-plan, .cross')) {
382 return labels.close;
383 }
384 if (element.matches('.cp-logo-ctrl')) {
385 return labels.company_info;
386 }
387 if (element.matches('.scctrl')) {
388 var sceneTitle = element.closest('li');
389 sceneTitle = sceneTitle ? sceneTitle.querySelector('.scene-title') : null;
390 return sceneTitle && sceneTitle.textContent.trim()
391 ? labels.scene + ': ' + sceneTitle.textContent.trim()
392 : labels.scene;
393 }
394 if (element.matches('.scene-navigation-list')) {
395 return labels.scene + ': ' + element.textContent.trim();
396 }
397 if (element.matches('.pnlm-hotspot-base, .pnlm-hotspot')) {
398 var hotspotText = element.textContent.replace(/\s+/g, ' ').trim();
399 return hotspotText ? hotspotText.slice(0, 160) : labels.hotspot;
400 }
401
402 var text = element.textContent.replace(/\s+/g, ' ').trim();
403 return text ? text.slice(0, 160) : labels.hotspot;
404 }
405
406 function isNativeControl(element) {
407 return /^(A|BUTTON|INPUT|SELECT|TEXTAREA)$/.test(element.tagName);
408 }
409
410 function prepareExternalHotspotLink(element) {
411 if (!element.matches('.pnlm-hotspot-base, .pnlm-hotspot')) {
412 return false;
413 }
414
415 var anchor = null;
416 if (element.parentElement && element.parentElement.matches('a[href]')) {
417 anchor = element.parentElement;
418 } else {
419 anchor = Array.prototype.find.call(element.children, function (child) {
420 return child.matches && child.matches('a[href]');
421 }) || null;
422 }
423
424 if (!anchor) {
425 return externalHotspotLinks.has(element);
426 }
427
428 externalHotspotLinks.set(element, {
429 url: anchor.href,
430 target: anchor.getAttribute('target') || '_self'
431 });
432
433 anchor.removeAttribute('href');
434 anchor.removeAttribute('target');
435 anchor.setAttribute('tabindex', '-1');
436 anchor.setAttribute('role', 'presentation');
437
438 element.addEventListener('click', activateExternalHotspotLink);
439 return true;
440 }
441
442 function activateExternalHotspotLink(event) {
443 var link = externalHotspotLinks.get(event.currentTarget);
444 if (!link || !link.url) {
445 return;
446 }
447
448 event.preventDefault();
449
450 var openInNewContext = link.target === '_blank' || event.ctrlKey || event.metaKey || event.shiftKey;
451 if (openInNewContext) {
452 var openedWindow = window.open(link.url, '_blank', 'noopener,noreferrer');
453 if (openedWindow) {
454 openedWindow.opener = null;
455 }
456 } else {
457 window.location.assign(link.url);
458 }
459 }
460
461 function enhanceControl(element) {
462 if (enhancedControls.has(element)) {
463 syncControlState(element);
464 return;
465 }
466
467 if (
468 element.matches('.ctrl') &&
469 element.parentElement &&
470 element.parentElement.matches('.explainer_button, .floor_map_button')
471 ) {
472 return;
473 }
474
475 enhancedControls.add(element);
476 element.classList.add('wpvr-a11y-control');
477 var isExternalHotspotLink = prepareExternalHotspotLink(element);
478 if (!isNativeControl(element)) {
479 element.setAttribute(
480 'role',
481 element.matches('.cp-logo-ctrl') ? 'group' : (isExternalHotspotLink ? 'link' : 'button')
482 );
483 element.setAttribute('tabindex', '0');
484 if (!element.matches('.cp-logo-ctrl')) {
485 element.addEventListener('keydown', activateControlFromKeyboard);
486 }
487 } else if (element.getAttribute('role') === 'presentation') {
488 element.removeAttribute('role');
489 }
490 if (!element.getAttribute('aria-label')) {
491 element.setAttribute('aria-label', labelFor(element));
492 }
493
494 associateControl(element);
495 associateTooltip(element);
496 syncControlState(element);
497 }
498
499 function activateControlFromKeyboard(event) {
500 if (event.key !== 'Enter' && event.key !== ' ') {
501 return;
502 }
503 event.preventDefault();
504 event.stopPropagation();
505 event.currentTarget.click();
506 }
507
508 function associateControl(element) {
509 var tour = getTour(element);
510 if (!tour || !tour.id) {
511 return;
512 }
513 var suffix = tour.id.replace(/^pano/, '');
514 var target = null;
515
516 if (element.matches('.explainer_button')) {
517 target = document.getElementById('explainer' + suffix);
518 } else if (element.matches('.generic_form_button')) {
519 target = document.getElementById('wpvr-generic-form' + suffix);
520 } else if (element.matches('.floor_map_button')) {
521 target = document.getElementById('wpvr-floor-map' + suffix);
522 } else if (element.matches('.custom-scene-navigation')) {
523 target = document.getElementById('custom-scene-navigation-nav' + suffix);
524 } else if (element.matches('.vrgcontrols')) {
525 target = document.getElementById('sccontrols' + suffix);
526 }
527
528 if (target && target.id) {
529 element.setAttribute('aria-controls', target.id);
530 element.setAttribute('aria-expanded', isVisible(target) ? 'true' : 'false');
531 }
532 }
533
534 function associateTooltip(element) {
535 if (!element.matches('.pnlm-hotspot-base, .pnlm-hotspot')) {
536 return;
537 }
538 var tooltip = element.querySelector(':scope > p');
539 if (!tooltip) {
540 return;
541 }
542 if (!tooltip.id) {
543 tooltipIndex += 1;
544 tooltip.id = 'wpvr-hotspot-tooltip-' + tooltipIndex;
545 }
546 element.setAttribute('aria-describedby', tooltip.id);
547 }
548
549 function syncControlState(element) {
550 if (element.matches('.audio_control')) {
551 element.setAttribute('aria-pressed', element.getAttribute('data-play') === 'on' ? 'true' : 'false');
552 }
553 if (element.matches('.scene-navigation-list, .floor-plan-pointer')) {
554 element.setAttribute(
555 'aria-current',
556 element.classList.contains('active') || element.classList.contains('add-pulse') ? 'true' : 'false'
557 );
558 }
559 if (element.matches('.scctrl')) {
560 var galleryItem = element.closest('.owl-item');
561 element.setAttribute('aria-current', galleryItem && galleryItem.classList.contains('clicked') ? 'true' : 'false');
562 }
563 if (element.matches('.pnlm-fullscreen-toggle-button, [id^="fullscreen"], .fullscreen-button')) {
564 var tour = getTour(element);
565 var fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement;
566 element.setAttribute(
567 'aria-pressed',
568 fullscreenElement && (fullscreenElement === tour || fullscreenElement.contains(tour)) ? 'true' : 'false'
569 );
570 }
571 if (element.matches('.pnlm-orientation-button, [id^="gyroscope"]')) {
572 var orientationTour = getTour(element);
573 var orientationViewer = getViewer(orientationTour);
574 element.setAttribute(
575 'aria-pressed',
576 orientationViewer && typeof orientationViewer.isOrientationActive === 'function' &&
577 orientationViewer.isOrientationActive() ? 'true' : 'false'
578 );
579 }
580 if (element.hasAttribute('aria-controls')) {
581 var controlled = document.getElementById(element.getAttribute('aria-controls'));
582 if (controlled) {
583 element.setAttribute('aria-expanded', isVisible(controlled) ? 'true' : 'false');
584 }
585 }
586 }
587
588 function enhanceDialog(dialog) {
589 if (!enhancedDialogs.has(dialog)) {
590 enhancedDialogs.add(dialog);
591 dialog.classList.add('wpvr-a11y-dialog');
592 dialog.setAttribute('role', 'dialog');
593 dialog.setAttribute('aria-modal', 'true');
594 dialog.setAttribute('tabindex', '-1');
595 if (!dialog.getAttribute('aria-label')) {
596 dialog.setAttribute('aria-label', labels.dialog);
597 }
598 dialog.addEventListener('keydown', handleDialogKeydown);
599 }
600 syncDialog(dialog);
601 }
602
603 function syncDialog(dialog) {
604 var visible = isVisible(dialog);
605 var previous = dialogStates.get(dialog);
606 dialog.setAttribute('aria-hidden', visible ? 'false' : 'true');
607 dialogStates.set(dialog, visible);
608
609 if (visible && previous !== true) {
610 focusDialog(dialog);
611 } else if (!visible && previous === true) {
612 restoreDialogFocus(dialog);
613 }
614 }
615
616 function focusDialog(dialog) {
617 var tour = getTour(dialog);
618 var opener = tour ? pendingOpeners.get(tour) : null;
619 if (!opener || !document.documentElement.contains(opener)) {
620 opener = tour;
621 }
622 dialog._wpvrOpener = opener;
623 window.setTimeout(function () {
624 var focusable = getFocusable(dialog);
625 (focusable[0] || dialog).focus();
626 }, 0);
627 }
628
629 function restoreDialogFocus(dialog) {
630 var opener = dialog._wpvrOpener;
631 if (opener && document.documentElement.contains(opener)) {
632 opener.focus();
633 }
634 dialog._wpvrOpener = null;
635 }
636
637 function getFocusable(dialog) {
638 return Array.prototype.filter.call(dialog.querySelectorAll(focusableSelector), function (element) {
639 return isVisible(element) && element.getAttribute('aria-hidden') !== 'true';
640 });
641 }
642
643 function handleDialogKeydown(event) {
644 var dialog = event.currentTarget;
645 if (event.key === 'Escape') {
646 event.preventDefault();
647 closeDialog(dialog);
648 return;
649 }
650 if (event.key !== 'Tab') {
651 return;
652 }
653
654 var focusable = getFocusable(dialog);
655 if (!focusable.length) {
656 event.preventDefault();
657 dialog.focus();
658 return;
659 }
660 var first = focusable[0];
661 var last = focusable[focusable.length - 1];
662 if (event.shiftKey && document.activeElement === first) {
663 event.preventDefault();
664 last.focus();
665 } else if (!event.shiftKey && document.activeElement === last) {
666 event.preventDefault();
667 first.focus();
668 }
669 }
670
671 function closeDialog(dialog) {
672 var close = dialog.querySelector('.close-explainer-video, .close-generic-form, .close-floor-map-plan, .cross');
673 if (close) {
674 close.click();
675 } else {
676 $(dialog).hide();
677 syncDialog(dialog);
678 return;
679 }
680
681 window.setTimeout(function () {
682 if (isVisible(dialog)) {
683 $(dialog).hide();
684 $(dialog).closest('.pano-wrap').removeClass('show-modal');
685 }
686 syncDialog(dialog);
687 }, 0);
688 }
689
690 function scan(root) {
691 var scope = root && root.querySelectorAll ? root : document;
692 var tours = [];
693 if (scope.matches && scope.matches('.pano-wrap.pnlm-container')) {
694 tours.push(scope);
695 }
696 tours = tours.concat(Array.prototype.slice.call(scope.querySelectorAll('.pano-wrap.pnlm-container')));
697
698 tours.forEach(function (tour) {
699 enhanceContainer(tour);
700 tour.querySelectorAll(controlSelector + ', .pnlm-hotspot-base, .pnlm-hotspot').forEach(enhanceControl);
701 tour.querySelectorAll(dialogSelector).forEach(enhanceDialog);
702 });
703 }
704
705 function queueScan(root) {
706 if (scanQueued) {
707 return;
708 }
709 scanQueued = true;
710 window.requestAnimationFrame(function () {
711 scanQueued = false;
712 scan(root || document);
713 });
714 }
715
716 document.addEventListener('click', function (event) {
717 var opener = event.target.closest(controlSelector + ', .pnlm-hotspot-base, .pnlm-hotspot');
718 var tour = getTour(event.target);
719 if (opener && tour) {
720 pendingOpeners.set(tour, opener);
721 }
722 if (event.target.closest('.pnlm-load-button') && tour) {
723 focusTourAfterLoad(tour);
724 }
725 window.setTimeout(function () {
726 if (tour) {
727 scan(tour);
728 }
729 }, 0);
730 }, true);
731
732 document.addEventListener('wpvr:viewer-ready', function (event) {
733 var container = event.detail && document.getElementById(event.detail.containerId);
734 if (container) {
735 scan(container);
736 }
737 });
738
739 document.addEventListener('fullscreenchange', function () {
740 queueScan(document);
741 });
742
743 $(function () {
744 scan(document);
745 var observer = new MutationObserver(function (mutations) {
746 var shouldScan = mutations.some(function (mutation) {
747 return mutation.type === 'childList' || mutation.attributeName === 'style' ||
748 mutation.attributeName === 'class' || mutation.attributeName === 'hidden' ||
749 mutation.attributeName === 'data-play';
750 });
751 if (shouldScan) {
752 queueScan(document);
753 }
754 });
755 observer.observe(document.body, {
756 childList: true,
757 subtree: true,
758 attributes: true,
759 attributeFilter: ['style', 'class', 'hidden', 'data-play']
760 });
761 });
762 })(jQuery);
763