PageSourceSearch

https://bitcoinprotocol.org/js/buy-crypto-menu.js?ver=1.2

js bitcoinprotocol.org collected 2026-09-28 06:34:24 UTC 11,739 bytes, 328 lines download raw bytes

1// Buy crypto menu on home page 
2// Make functions globally available
3window.handleBuyButtonClick = function(coin, shouldScroll = false) {
4    updateCoinSelection(coin);
5    if (shouldScroll) {
6        document.getElementById('getting-started').scrollIntoView({ behavior: 'smooth' });
7    }
8};
9
10window.scrollToWidget = function() {
11    document.getElementById('getting-started').scrollIntoView({ behavior: 'smooth' });
12};
13
14// Crypto name mapping 
15// Split multi-word crypto names on line 85 below
16const currencyNames = {
17    btc: 'Bitcoin (BTC)',
18    bch: 'Bitcoin Cash (BCH)',
19    eth: 'Ethereum (ETH)',
20    sol: 'Solana (SOL)',
21    usdt: 'Tether (USDT)',
22    usdc: 'USD Coin (USDC)',
23    ltc: 'Litecoin (LTC)',
24    doge: 'Dogecoin (DOGE)',
25    shib: 'Shiba Inu (SHIBA)',
26    pepe: 'Pepe (PEPE)',
27    ada: 'Cardano (ADA)',
28    pol: 'Polygon (POL)',
29    sui: 'Sui (SUI)',
30    wlfi: 'WLFI (WLFI)',
31    bnb: 'BNB (BNB)',
32    xrp: 'XRP (XRP)',
33};
34
35function getUrlParameter(name) {
36    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
37    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
38    var results = regex.exec(location.search);
39    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
40}
41
42function updateGeminiUrl(coin, amount) {
43    const continueBtn = document.getElementById('continue-btn');
44    if (continueBtn) {
45        const cleanAmount = parseFloat(amount.replace(/[^0-9.]/g, '')).toFixed(2);
46        const baseUrl = 'https://exchange.gemini.com/register';
47        const params = new URLSearchParams({
48            referral: 'fEU0MR',
49            type: 'referral',
50            symbol: coin,
51            amount: cleanAmount
52        });
53        continueBtn.href = `${baseUrl}?${params.toString()}`;
54    }
55}
56
57function updateCoinSelection(coin) {
58    const coinSelect = document.getElementById('coin-select');
59    if (coinSelect) {
60        coinSelect.value = coin;
61        
62        const customSelect = document.querySelector('.custom-select');
63        if (customSelect) {
64            const selectSelected = customSelect.querySelector('.select-selected');
65            const selectItems = customSelect.querySelector('.select-items');
66            
67            const option = selectItems.querySelector(`div[data-value="${coin}"]`);
68            if (option) {
69                const text = option.querySelector('span').textContent;
70                const img = option.querySelector('img').src;
71                
72                selectSelected.querySelector('img').src = img;
73                selectSelected.querySelector('span').textContent = text;
74            }
75        }
76
77        const continueBtn = document.getElementById('continue-btn');
78        if (continueBtn) {
79            continueBtn.textContent = `Continue & Earn $50 Free`;
80        }
81
82        const amountDisplay = document.querySelector('.amount-display h1');
83        if (amountDisplay) {
84            updateGeminiUrl(coin, amountDisplay.textContent);
85        }
86
87        // Split multi-word cryptocurrency names properly 
88        let displayName;
89        switch(coin) {
90            case 'bch':
91                displayName = 'Bitcoin Cash';
92                break;
93            case 'shib':
94                displayName = 'Shiba Inu';
95                break;
96            case 'usdc':
97                displayName = 'USD Coin';
98                break;
99            default:
100                displayName = coin === 'currency' ? 'Crypto' : (currencyNames[coin] || coin.toUpperCase()).split(' ')[0];
101        }
102        document.querySelectorAll('.selected-coin-display').forEach(element => {
103            element.innerText = displayName;
104        });
105
106        if (coin !== 'currency' && document.readyState === 'complete') {
107            const newUrl = `${window.location.protocol}//${window.location.host}${window.location.pathname}?crypto=${coin}`;
108            window.history.pushState({ path: newUrl }, '', newUrl);
109        } else if (coin === 'currency' && window.location.search.includes('crypto=')) {
110            const newUrl = `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
111            window.history.pushState({ path: newUrl }, '', newUrl);
112        }
113    }
114}
115
116function setupAmountButtons() {
117    const amountButtons = document.querySelectorAll('.amount-btn');
118    const amountDisplay = document.querySelector('.amount-display h1');
119    
120    function formatAmount(amount) {
121        const num = parseInt(amount.replace(/[^0-9]/g, ''));
122        return `$${num.toFixed(2)}`;
123    }
124    
125    amountButtons.forEach(button => {
126        button.addEventListener('click', function() {
127            amountButtons.forEach(btn => btn.classList.remove('active'));
128            this.classList.add('active');
129            
130            if (amountDisplay) {
131                const formattedAmount = formatAmount(this.textContent);
132                amountDisplay.textContent = formattedAmount;
133                
134                const coinSelect = document.getElementById('coin-select');
135                if (coinSelect) {
136                    updateGeminiUrl(coinSelect.value, formattedAmount);
137                }
138            }
139        });
140    });
141
142    if (amountDisplay && amountButtons.length > 0) {
143        const activeButton = amountButtons[0];
144        const formattedAmount = formatAmount(activeButton.textContent);
145        amountDisplay.textContent = formattedAmount;
146        
147        const coinSelect = document.getElementById('coin-select');
148        if (coinSelect) {
149            updateGeminiUrl(coinSelect.value, formattedAmount);
150        }
151    }
152}
153
154function initializeCustomSelect(cryptoParam = null) {
155    const customSelect = document.querySelector('.custom-select');
156    if (!customSelect) return;
157
158    const selectSelected = customSelect.querySelector('.select-selected');
159    const selectItems = customSelect.querySelector('.select-items');
160    const select = customSelect.querySelector('select');
161    let closeTimeout = null;
162    let touchStartY = 0;
163    let isScrolling = false;
164    let touchStartTime = 0;
165    let isInitializing = true;
166
167    const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
168    const getDelay = () => isTouchDevice ? 500 : 0;
169
170    function toggleDropdown(e) {
171        if (e) {
172            e.preventDefault();
173            e.stopPropagation();
174        }
175        selectItems.classList.toggle('select-hide');
176        selectSelected.classList.toggle('select-arrow-active');
177    }
178
179    function handleOptionSelect(div) {
180        if (closeTimeout) {
181            clearTimeout(closeTimeout);
182        }
183
184        const value = div.getAttribute('data-value');
185        const text = div.querySelector('span').textContent;
186        const img = div.querySelector('img').src;
187        
188        if (isTouchDevice) {
189            closeTimeout = setTimeout(() => {
190                selectItems.classList.add('select-hide');
191                selectSelected.classList.remove('select-arrow-active');
192                
193                select.value = value;
194                selectSelected.querySelector('img').src = img;
195                selectSelected.querySelector('span').textContent = text;
196                
197                const event = new Event('change');
198                select.dispatchEvent(event);
199            }, getDelay());
200        } else {
201            selectItems.classList.add('select-hide');
202            selectSelected.classList.remove('select-arrow-active');
203            
204            select.value = value;
205            selectSelected.querySelector('img').src = img;
206            selectSelected.querySelector('span').textContent = text;
207            
208            const event = new Event('change');
209            select.dispatchEvent(event);
210        }
211    }
212
213    if (isTouchDevice) {
214        selectItems.addEventListener('touchstart', function(e) {
215            touchStartY = e.touches[0].clientY;
216            touchStartTime = Date.now();
217            isScrolling = false;
218        }, { passive: true });
219
220        selectItems.addEventListener('touchmove', function(e) {
221            const touchY = e.touches[0].clientY;
222            const diff = touchStartY - touchY;
223            if (Math.abs(diff) > 5) {
224                isScrolling = true;
225            }
226        }, { passive: true });
227
228        selectItems.querySelectorAll('div').forEach(div => {
229            div.addEventListener('touchend', function(e) {
230                e.preventDefault();
231                e.stopPropagation();
232                const touchDuration = Date.now() - touchStartTime;
233                if (!isScrolling && touchDuration < 200) {
234                    handleOptionSelect(this);
235                }
236            });
237        });
238
239        selectSelected.addEventListener('touchend', function(e) {
240            e.preventDefault();
241            e.stopPropagation();
242            toggleDropdown(e);
243        });
244
245        selectSelected.addEventListener('touchstart', function(e) {
246            e.preventDefault();
247        }, { passive: false });
248    }
249
250    selectSelected.addEventListener('click', function(e) {
251        e.preventDefault();
252        e.stopPropagation();
253        toggleDropdown(e);
254    });
255
256    selectItems.querySelectorAll('div').forEach(div => {
257        div.addEventListener('click', function(e) {
258            e.preventDefault();
259            e.stopPropagation();
260            handleOptionSelect(this);
261        });
262    });
263
264    document.addEventListener('click', function(e) {
265        if (!customSelect.contains(e.target)) {
266            if (closeTimeout) {
267                clearTimeout(closeTimeout);
268            }
269            
270            if (isTouchDevice) {
271                closeTimeout = setTimeout(() => {
272                    selectItems.classList.add('select-hide');
273                    selectSelected.classList.remove('select-arrow-active');
274                }, 400);
275            } else {
276                selectItems.classList.add('select-hide');
277                selectSelected.classList.remove('select-arrow-active');
278            }
279        }
280    });
281
282    if (cryptoParam) {
283        const option = selectItems.querySelector(`div[data-value="${cryptoParam}"]`);
284        if (option) {
285            handleOptionSelect(option);
286        }
287    } else {
288        const firstOption = selectItems.querySelector('div');
289        if (firstOption) {
290            const value = firstOption.getAttribute('data-value');
291            const text = firstOption.querySelector('span').textContent;
292            const img = firstOption.querySelector('img').src;
293            
294            select.value = value;
295            selectSelected.querySelector('img').src = img;
296            selectSelected.querySelector('span').textContent = text;
297        }
298    }
299
300    select.addEventListener('change', function() {
301        if (!isInitializing) {
302            updateCoinSelection(this.value);
303        }
304    });
305
306    setTimeout(() => {
307        isInitializing = false;
308    }, 100);
309
310    window.addEventListener('beforeunload', function() {
311        if (closeTimeout) {
312            clearTimeout(closeTimeout);
313        }
314    });
315}
316
317document.addEventListener('DOMContentLoaded', function() {
318    const cryptoParam = getUrlParameter('crypto');
319    setupAmountButtons();
320    initializeCustomSelect(cryptoParam);
321    updateCoinSelection(cryptoParam || 'currency');
322    
323    if (!cryptoParam) {
324        document.querySelectorAll('.selected-coin-display').forEach(element => {
325            element.innerText = 'Crypto';
326        });
327    }
328}); 

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.