1(function ($) { 2 const CTCCoupon = { 3 4 /** 5 * Init 6 */ 7 init: function () { 8 this._bind(); 9 }, 10 11 /** 12 * Binds events 13 */ 14 _bind: function () { 15 $( document ).on( 'click', '.ctc-coupon-toggle-link', this.toggleDetails ); 16 $( document ).on( 'click', '.ctc-coupon-link', this.handleClick ); 17 }, 18 19 /** 20 * Copy text to clipboard using CTC CopyEngine. 21 * 22 * @param {string} text Text to copy. 23 * @return {Promise<boolean>} Success status. 24 */ 25 copyToClipboard: async function ( text ) { 26 // Method 1: Use CTC CopyEngine. 27 if ( window.CTC && window.CTC.CopyEngine ) { 28 try { 29 const copyEngine = new window.CTC.CopyEngine(); 30 const result = await copyEngine.execute( { value: text } ); 31 if ( result.success ) { 32 return true; 33 } 34 } catch ( err ) { 35 // Fall through to fallbacks. 36 } 37 } 38 39 // Method 2: Clipboard API. 40 if ( navigator.clipboard && navigator.clipboard.writeText ) { 41 try { 42 await navigator.clipboard.writeText( text ); 43 return true; 44 } catch ( err ) { 45 // Fall through. 46 } 47 } 48 49 // Method 3: execCommand fallback. 50 try { 51 const textArea = document.createElement( 'textarea' ); 52 textArea.value = text; 53 textArea.style.cssText = 'position:fixed;opacity:0;pointer-events:none;'; 54 document.body.appendChild( textArea ); 55 textArea.select(); 56 const success = document.execCommand( 'copy' ); 57 document.body.removeChild( textArea ); 58 return success; 59 } catch ( err ) { 60 return false; 61 } 62 }, 63 64 /** 65 * Handle click 66 */ 67 handleClick: async function (event) { 68 event.preventDefault() 69 70 const self = $( this ) 71 const parent = self.parents( '.ctc-coupon' ) 72 if ( parent.hasClass( 'ctc-coupon-clicked' ) ) { 73 return 74 } 75 76 const href = self.attr( 'href' ) 77 const target = self.attr( 'target' ) 78 const couponCode = parent.find( '.ctc-coupon-code' ).text().trim() || '' 79 80 parent.addClass( 'ctc-coupon-clicked' ) 81 82 await CTCCoupon.copyToClipboard( couponCode ) 83 84 window.open( href, target ) 85 }, 86 87 /** 88 * Handle click 89 */ 90 oldHandleClick: function (event) { 91 event.preventDefault(); 92 93 const self = $( this ) 94 const href = self.data( 'href' ) 95 const target = self.data( 'target' ) 96 const btn = self.find( '.ctc-coupon-button' ) 97 98 // Clicked then open the link 99 if ( ! self.hasClass( 'ctc-coupon-link-clicked' ) ) { 100 window.open( href, target ) 101 102 self.addClass( 'ctc-coupon-link-clicked' ) 103 btn.text( 'Copy Code' ) 104 } 105 106 if ( self.hasClass( 'ctc-coupon-link-clicked' ) ) { 107 self.addClass( 'ctc-coupon-link-copied' ) 108 btn.text( 'Copied' ) 109 } 110 }, 111 112 /** 113 * Toggle Details 114 */ 115 toggleDetails: function (event) { 116 event.preventDefault(); 117 118 const self = $( this ) 119 const coupon = self.parents( '.ctc-coupon' ) 120 const details = coupon.find( '.ctc-toggle-details' ) 121 122 details.slideToggle( 'fast' ) 123 } 124 }; 125 126 /** 127 * Initialization 128 */ 129 $( 130 function () { 131 CTCCoupon.init(); 132 } 133 ); 134 135})( jQuery );
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.