1(function () { 2 'use strict'; 3 4 var labels = window.timberinProfessionalCart || { 5 decrease: 'Decrease quantity', 6 increase: 'Increase quantity' 7 }; 8 9 function setMissingCellLabels(form) { 10 var names = ['product-price', 'product-quantity', 'product-subtotal']; 11 12 names.forEach(function (className) { 13 var heading = form.querySelector('thead th.' + className); 14 var text = heading ? heading.textContent.replace(/\s+/g, ' ').trim() : ''; 15 16 if (!text) { 17 return; 18 } 19 20 form.querySelectorAll('tr.cart_item td.' + className).forEach(function (cell) { 21 if (!cell.getAttribute('data-title')) { 22 cell.setAttribute('data-title', text); 23 } 24 }); 25 }); 26 } 27 28 function createButton(direction) { 29 var button = document.createElement('button'); 30 button.type = 'button'; 31 button.className = direction + ' timberin-cart-quantity__button'; 32 button.setAttribute('data-timberin-quantity', direction); 33 button.setAttribute('aria-label', direction === 'minus' ? labels.decrease : labels.increase); 34 button.textContent = direction === 'minus' ? 'â' : '+'; 35 return button; 36 } 37 38 function preferNativeControl(quantity, direction) { 39 var controls = Array.prototype.slice.call(quantity.querySelectorAll('.' + direction)); 40 var nativeControl = controls.find(function (control) { 41 return !control.hasAttribute('data-timberin-quantity'); 42 }); 43 44 if (nativeControl) { 45 controls.forEach(function (control) { 46 if (control !== nativeControl && control.hasAttribute('data-timberin-quantity')) { 47 control.remove(); 48 } 49 }); 50 return nativeControl; 51 } 52 53 return controls[0] || null; 54 } 55 56 function enhanceQuantity(quantity) { 57 var input = quantity.querySelector('input.qty'); 58 59 if (!input) { 60 return; 61 } 62 63 var minus = preferNativeControl(quantity, 'minus'); 64 var plus = preferNativeControl(quantity, 'plus'); 65 66 if (!minus) { 67 minus = createButton('minus'); 68 quantity.insertBefore(minus, input); 69 } else if (!minus.getAttribute('aria-label')) { 70 minus.setAttribute('aria-label', labels.decrease); 71 } 72 73 if (!plus) { 74 plus = createButton('plus'); 75 input.insertAdjacentElement('afterend', plus); 76 } else if (!plus.getAttribute('aria-label')) { 77 plus.setAttribute('aria-label', labels.increase); 78 } 79 80 quantity.setAttribute('data-timberin-quantity-ready', 'true'); 81 } 82 83 function mount() { 84 document.querySelectorAll('form.woocommerce-cart-form').forEach(function (form) { 85 setMissingCellLabels(form); 86 form.querySelectorAll('.quantity').forEach(enhanceQuantity); 87 }); 88 } 89 90 function updateAddedControl(button) { 91 var quantity = button.closest('.quantity'); 92 var input = quantity ? quantity.querySelector('input.qty') : null; 93 94 if (!input || input.disabled || input.readOnly) { 95 return; 96 } 97 98 var direction = button.getAttribute('data-timberin-quantity'); 99 var min = input.min === '' ? 0 : parseFloat(input.min); 100 var max = input.max === '' ? Infinity : parseFloat(input.max); 101 var step = input.step === '' || input.step === 'any' ? 1 : parseFloat(input.step); 102 var value = input.value === '' ? min : parseFloat(input.value); 103 104 if (!Number.isFinite(min)) { 105 min = 0; 106 } 107 if (!Number.isFinite(step) || step <= 0) { 108 step = 1; 109 } 110 if (!Number.isFinite(value)) { 111 value = min; 112 } 113 114 value += direction === 'minus' ? -step : step; 115 value = Math.max(min, Math.min(max, value)); 116 117 var decimals = (String(step).split('.')[1] || '').length; 118 input.value = decimals ? value.toFixed(decimals) : String(Math.round(value)); 119 input.dispatchEvent(new Event('input', { bubbles: true })); 120 input.dispatchEvent(new Event('change', { bubbles: true })); 121 } 122 123 document.addEventListener('click', function (event) { 124 var button = event.target.closest('[data-timberin-quantity]'); 125 126 if (!button) { 127 return; 128 } 129 130 event.preventDefault(); 131 updateAddedControl(button); 132 }); 133 134 if (document.readyState === 'loading') { 135 document.addEventListener('DOMContentLoaded', mount, { once: true }); 136 } else { 137 mount(); 138 } 139 140 window.addEventListener('pageshow', mount); 141 142 if (window.jQuery) { 143 window.jQuery(document.body).on('updated_wc_div updated_cart_totals', function () { 144 window.setTimeout(mount, 0); 145 }); 146 } 147 148 var root = document.querySelector('.woocommerce') || document.body; 149 if (window.MutationObserver && root) { 150 var timer; 151 new MutationObserver(function () { 152 window.clearTimeout(timer); 153 timer = window.setTimeout(mount, 0); 154 }).observe(root, { childList: true, subtree: true }); 155 } 156}());
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.