1/** 2 * TechBBQ Tito â sticky CTA sync for ticket widgets using tito-button. 3 * 4 * Mobile sticky bar uses one <tito-button>. On card selection, attrs are copied 5 * from the selected card's <tito-button> (recreated so Tito picks up changes). 6 */ 7( function () { 8 'use strict'; 9 10 const ATTRS = [ 'event', 'releases', 'discount-code' ]; 11 12 const readSource = ( card ) => { 13 const source = card?.querySelector( 'tito-button' ); 14 15 if ( ! source ) { 16 return null; 17 } 18 19 return { 20 label: source.textContent?.trim() || '', 21 ticketKey: card.dataset.ticketKey || '', 22 attrs: ATTRS.reduce( ( acc, name ) => { 23 const value = source.getAttribute( name ); 24 25 if ( value ) { 26 acc[ name ] = value; 27 } 28 29 return acc; 30 }, {} ), 31 }; 32 }; 33 34 const attrsMatch = ( el, attrs ) => 35 ATTRS.every( ( name ) => ( el.getAttribute( name ) || '' ) === ( attrs[ name ] || '' ) ); 36 37 const setLabel = ( el, label ) => { 38 if ( ! label ) { 39 return; 40 } 41 42 const widgetLabel = el.querySelector( '.tito-widget-button span, .tito-widget-button' ); 43 44 if ( widgetLabel ) { 45 widgetLabel.textContent = label; 46 return; 47 } 48 49 el.textContent = label; 50 }; 51 52 /** 53 * Sync sticky checkout control to the selected card. 54 * 55 * @param {Element|null} sticky Current sticky control (button or tito-button). 56 * @param {Element|null} card Selected card. 57 * @return {Element|null} Sticky element after sync (may be a new node). 58 */ 59 window.techbbqSyncTitoStickyButton = function ( sticky, card ) { 60 if ( ! sticky || sticky.tagName !== 'TITO-BUTTON' ) { 61 return sticky || null; 62 } 63 64 const source = readSource( card ); 65 66 if ( ! source ) { 67 return sticky; 68 } 69 70 if ( source.ticketKey ) { 71 sticky.dataset.ticketKey = source.ticketKey; 72 } 73 74 if ( attrsMatch( sticky, source.attrs ) ) { 75 setLabel( sticky, source.label ); 76 return sticky; 77 } 78 79 const next = document.createElement( 'tito-button' ); 80 81 next.className = sticky.className; 82 83 ATTRS.forEach( ( name ) => { 84 if ( source.attrs[ name ] ) { 85 next.setAttribute( name, source.attrs[ name ] ); 86 } 87 } ); 88 89 if ( source.ticketKey ) { 90 next.dataset.ticketKey = source.ticketKey; 91 } 92 93 next.textContent = source.label || sticky.textContent?.trim() || ''; 94 sticky.replaceWith( next ); 95 96 return next; 97 }; 98 99 window.techbbqBindTitoTicketButtons = function ( root, cards, stickyButton, cardButtons ) { 100 const titoEnabled = root?.dataset.titoEnabled === '1'; 101 102 if ( titoEnabled ) { 103 return; 104 } 105 106 const bindNoop = ( button ) => { 107 // A button pointed at a URL is a link, and must be left alone. This no-op exists for a 108 // card whose checkout is switched off and which therefore has nowhere to go; calling 109 // preventDefault on an anchor that does have somewhere to go silently kills a working 110 // link, and it fails quietly, because the markup looks perfect either way. 111 if ( 'A' === button.tagName && button.getAttribute( 'href' ) ) { 112 return; 113 } 114 115 button.addEventListener( 'click', ( event ) => { 116 event.preventDefault(); 117 } ); 118 }; 119 120 cardButtons.forEach( bindNoop ); 121 122 if ( stickyButton ) { 123 bindNoop( stickyButton ); 124 } 125 }; 126}() );
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.