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);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.