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