1/* global Cookies */ 2jQuery( function ( $ ) { 3 // Orderby 4 $( '.woocommerce-ordering' ).on( 'change', 'select.orderby', function () { 5 $( this ).closest( 'form' ).trigger( 'submit' ); 6 } ); 7 8 // Target quantity inputs on product pages 9 $( 'input.qty:not(.product-quantity input.qty)' ).each( function () { 10 var min = parseFloat( $( this ).attr( 'min' ) ); 11 12 if ( min >= 0 && parseFloat( $( this ).val() ) < min ) { 13 $( this ).val( min ); 14 } 15 } ); 16 17 // Global accessibility handler for all links with role="button" 18 // This ensures both spacebar and enter keypresses trigger click events, as per ARIA specification 19 document.body.addEventListener( 'keydown', function ( event ) { 20 if ( ! event.target.matches( 'a[role="button"]' ) ) { 21 return; 22 } 23 24 if ( event.key === ' ' || event.key === 'Enter' ) { 25 event.preventDefault(); 26 event.target.click(); 27 } 28 } ); 29 30 var noticeID = $( '.woocommerce-store-notice' ).data( 'noticeId' ) || '', 31 cookieName = 'store_notice' + noticeID; 32 33 // Check the value of that cookie and show/hide the notice accordingly 34 if ( 'hidden' === Cookies.get( cookieName ) ) { 35 $( '.woocommerce-store-notice' ).hide(); 36 } else { 37 $( '.woocommerce-store-notice' ).show(); 38 39 // Set a cookie and hide the store notice when the dismiss button is clicked 40 function store_notice_click_handler( event ) { 41 Cookies.set( cookieName, 'hidden', { path: '/' } ); 42 $( '.woocommerce-store-notice' ).hide(); 43 event.preventDefault(); 44 $( '.woocommerce-store-notice__dismiss-link' ).off( 45 'click', 46 store_notice_click_handler 47 ); 48 } 49 50 $( '.woocommerce-store-notice__dismiss-link' ).on( 51 'click', 52 store_notice_click_handler 53 ); 54 } 55 56 // Make form field descriptions toggle on focus. 57 if ( $( '.woocommerce-input-wrapper span.description' ).length ) { 58 $( document.body ).on( 'click', function () { 59 $( '.woocommerce-input-wrapper span.description:visible' ) 60 .prop( 'aria-hidden', true ) 61 .slideUp( 250 ); 62 } ); 63 } 64 65 $( '.woocommerce-input-wrapper' ).on( 'click', function ( event ) { 66 event.stopPropagation(); 67 } ); 68 69 $( '.woocommerce-input-wrapper :input' ) 70 .on( 'keydown', function ( event ) { 71 var input = $( this ), 72 parent = input.parent(), 73 description = parent.find( 'span.description' ); 74 75 if ( 76 27 === event.which && 77 description.length && 78 description.is( ':visible' ) 79 ) { 80 description.prop( 'aria-hidden', true ).slideUp( 250 ); 81 event.preventDefault(); 82 return false; 83 } 84 } ) 85 .on( 'click focus', function () { 86 var input = $( this ), 87 parent = input.parent(), 88 description = parent.find( 'span.description' ); 89 90 parent.addClass( 'currentTarget' ); 91 92 $( 93 '.woocommerce-input-wrapper:not(.currentTarget) span.description:visible' 94 ) 95 .prop( 'aria-hidden', true ) 96 .slideUp( 250 ); 97 98 if ( description.length && description.is( ':hidden' ) ) { 99 description.prop( 'aria-hidden', false ).slideDown( 250 ); 100 } 101 102 parent.removeClass( 'currentTarget' ); 103 } ); 104 105 // Common scroll to element code. 106 $.scroll_to_notices = function ( scrollElement ) { 107 if ( scrollElement.length ) { 108 $( 'html, body' ).animate( 109 { 110 scrollTop: scrollElement.offset().top - 100, 111 }, 112 1000 113 ); 114 } 115 }; 116 117 // Show password visibility hover icon on woocommerce forms 118 $( '.woocommerce form .woocommerce-Input[type="password"]' ).wrap( 119 '<span class="password-input"></span>' 120 ); 121 // Add 'password-input' class to the password wrapper in checkout page. 122 $( '.woocommerce form input' ) 123 .filter( ':password' ) 124 .parent( 'span' ) 125 .addClass( 'password-input' ); 126 127 $( '.password-input' ).each( function () { 128 const describedBy = $( this ).find( 'input' ).attr( 'id' ); 129 $( this ).append( 130 '<button type="button" class="show-password-input" aria-label="' + 131 woocommerce_params.i18n_password_show + 132 '" aria-describedBy="' + 133 describedBy + 134 '"></button>' 135 ); 136 } ); 137 138 $( '.show-password-input' ).on( 'click', function ( event ) { 139 event.preventDefault(); 140 141 if ( $( this ).hasClass( 'display-password' ) ) { 142 $( this ).removeClass( 'display-password' ); 143 $( this ).attr( 144 'aria-label', 145 woocommerce_params.i18n_password_show 146 ); 147 } else { 148 $( this ).addClass( 'display-password' ); 149 $( this ).attr( 150 'aria-label', 151 woocommerce_params.i18n_password_hide 152 ); 153 } 154 if ( $( this ).hasClass( 'display-password' ) ) { 155 $( this ) 156 .siblings( [ 'input[type="password"]' ] ) 157 .prop( 'type', 'text' ); 158 } else { 159 $( this ) 160 .siblings( 'input[type="text"]' ) 161 .prop( 'type', 'password' ); 162 } 163 164 $( this ).siblings( 'input' ).focus(); 165 } ); 166 167 $( 'a.coming-soon-footer-banner-dismiss' ).on( 'click', function ( e ) { 168 var target = $( e.target ); 169 $.ajax( { 170 type: 'post', 171 url: target.data( 'rest-url' ), 172 data: { 173 woocommerce_meta: { 174 coming_soon_banner_dismissed: 'yes', 175 }, 176 }, 177 beforeSend: function ( xhr ) { 178 xhr.setRequestHeader( 179 'X-WP-Nonce', 180 target.data( 'rest-nonce' ) 181 ); 182 },
183 complete: function () { 184 $( '#coming-soon-footer-banner' ).hide(); 185 }, 186 } ); 187 } ); 188 189 $( document.body ).on( 190 'item_removed_from_classic_cart updated_wc_div', 191 focus_populate_live_region 192 ); 193} ); 194 195/** 196 * Focus on the first notice element on the page. 197 * 198 * Populated live regions don't always are announced by screen readers. 199 * This function focus on the first notice message with the role="alert" 200 * attribute to make sure it's announced. 201 */ 202function focus_populate_live_region() { 203 var noticeClasses = [ 204 'woocommerce-message', 205 'woocommerce-error', 206 'wc-block-components-notice-banner', 207 ]; 208 var noticeSelectors = noticeClasses 209 .map( function ( className ) { 210 return '.' + className + '[role="alert"]'; 211 } ) 212 .join( ', ' ); 213 var noticeElements = document.querySelectorAll( noticeSelectors ); 214 215 if ( noticeElements.length === 0 ) { 216 return; 217 } 218 219 var firstNotice = noticeElements[ 0 ]; 220 221 firstNotice.setAttribute( 'tabindex', '-1' ); 222 223 // Wait for the element to get the tabindex attribute so it can be focused. 224 var delayFocusNoticeId = setTimeout( function () { 225 firstNotice.focus(); 226 clearTimeout( delayFocusNoticeId ); 227 }, 500 ); 228} 229 230/** 231 * Refresh the sorted by live region. 232 */ 233function refresh_sorted_by_live_region() { 234 var sorted_by_live_region = document.querySelector( 235 '.woocommerce-result-count' 236 ); 237 238 if ( sorted_by_live_region ) { 239 var text = sorted_by_live_region.innerHTML; 240 sorted_by_live_region.setAttribute( 'aria-hidden', 'true' ); 241 242 var sorted_by_live_region_id = setTimeout( function () { 243 sorted_by_live_region.setAttribute( 'aria-hidden', 'false' ); 244 sorted_by_live_region.innerHTML = ''; 245 sorted_by_live_region.innerHTML = text; 246 clearTimeout( sorted_by_live_region_id ); 247 }, 2000 ); 248 } 249} 250 251function on_document_ready() { 252 focus_populate_live_region(); 253 refresh_sorted_by_live_region(); 254} 255 256document.addEventListener( 'DOMContentLoaded', on_document_ready );
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.