1/** 2 * Front-end: download-features tabs + deep links from download-card more links. 3 * Tab chrome classes: .wsft-tabs / .wsft-tab (shared). 4 */ 5( function () { 6 'use strict'; 7 8 var TAB_SEL = '.wsft-tab[data-wsft-download-features-tab]'; 9 10 function getRoot( el ) { 11 return el ? el.closest( '[data-wsft-download-features]' ) : null; 12 } 13 14 function selectTab( root, index ) { 15 if ( ! root ) { 16 return; 17 } 18 19 var i = parseInt( index, 10 ); 20 if ( isNaN( i ) || i < 0 ) { 21 i = 0; 22 } 23 24 var tabs = root.querySelectorAll( TAB_SEL ); 25 var panels = root.querySelectorAll( '[data-wsft-download-features-panel]' ); 26 if ( ! tabs.length ) { 27 return; 28 } 29 if ( i >= tabs.length ) { 30 i = 0; 31 } 32 33 tabs.forEach( function ( tab ) { 34 var active = 35 parseInt( tab.getAttribute( 'data-wsft-download-features-tab' ), 10 ) === i; 36 tab.classList.toggle( 'is-active', active ); 37 tab.setAttribute( 'aria-selected', active ? 'true' : 'false' ); 38 tab.setAttribute( 'tabindex', active ? '0' : '-1' ); 39 var item = tab.closest( '.wsft-tabs__item' ); 40 if ( item ) { 41 item.classList.toggle( 'wsft-tabs__item--active', active ); 42 } 43 } ); 44 45 panels.forEach( function ( panel ) { 46 var active = 47 parseInt( panel.getAttribute( 'data-wsft-download-features-panel' ), 10 ) === 48 i; 49 panel.classList.toggle( 'is-active', active ); 50 if ( active ) { 51 panel.removeAttribute( 'hidden' ); 52 } else { 53 panel.setAttribute( 'hidden', '' ); 54 } 55 } ); 56 } 57 58 function scrollToIntegrations() { 59 var target = document.getElementById( 'integrations' ); 60 if ( target && typeof target.scrollIntoView === 'function' ) { 61 target.scrollIntoView( { behavior: 'smooth', block: 'start' } ); 62 } 63 } 64 65 function onDocumentClick( event ) { 66 var more = event.target.closest( 67 'a.wsft-download-card__more-link[data-wsft-download-features-tab]' 68 ); 69 if ( more ) { 70 var root = document.querySelector( '[data-wsft-download-features]' ); 71 if ( root ) { 72 event.preventDefault(); 73 selectTab( root, more.getAttribute( 'data-wsft-download-features-tab' ) ); 74 scrollToIntegrations(); 75 } 76 return; 77 } 78 79 var tabBtn = event.target.closest( TAB_SEL ); 80 if ( tabBtn ) { 81 selectTab( 82 getRoot( tabBtn ), 83 tabBtn.getAttribute( 'data-wsft-download-features-tab' ) 84 ); 85 } 86 } 87 88 function onKeydown( event ) { 89 var tabBtn = event.target.closest( TAB_SEL + '[role="tab"]' ); 90 if ( ! tabBtn ) { 91 return; 92 } 93 if ( event.key !== 'ArrowRight' && event.key !== 'ArrowLeft' ) { 94 return; 95 } 96 97 var root = getRoot( tabBtn ); 98 if ( ! root ) { 99 return; 100 } 101 var tabs = Array.prototype.slice.call( root.querySelectorAll( TAB_SEL + '[role="tab"]' ) ); 102 var current = tabs.indexOf( tabBtn ); 103 if ( current < 0 ) { 104 return; 105 } 106 107 event.preventDefault(); 108 var next = 109 event.key === 'ArrowRight' 110 ? ( current + 1 ) % tabs.length 111 : ( current - 1 + tabs.length ) % tabs.length; 112 selectTab( root, next ); 113 tabs[ next ].focus(); 114 } 115 116 document.addEventListener( 'click', onDocumentClick ); 117 document.addEventListener( 'keydown', onKeydown ); 118 119 document.addEventListener( 'DOMContentLoaded', function () { 120 var hash = ( window.location.hash || '' ).replace( /^#/, '' ); 121 if ( hash.indexOf( 'integrations' ) !== 0 ) { 122 return; 123 } 124 var root = document.querySelector( '[data-wsft-download-features]' ); 125 if ( ! root ) { 126 return; 127 } 128 var match = hash.match( /^integrations-(\d+)$/ ); 129 if ( match ) { 130 selectTab( root, match[ 1 ] ); 131 } 132 } ); 133} )();
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.