1// @ts-nocheck 2// i18n (T-20260816-04): AC3 -- Marketplace toolbar/AJAX'taki culture-prefix garantisi ayni 3// desendeki (X-Requested-With) diger public AJAX akislarina da uygulanir. PathBase <body 4// data-pathbase> ile gelir (TR'de bos string, /en'de "/en"). 5// PR #1608 review yesil kalem: klasik <script> dosyalarinda top-level "function" bildirimi 6// window'a (global) DUSER -- ayni isimli bir fonksiyon baska bir sayfanin JS dosyasinda 7// (sets/detail.js) da tanimliysa, ikisi de ayni sayfada yuklenirse biri digerini SESSIZCE 8// ezer. IIFE'ye alinarak bu dosyanin scope'una hapsedilir, disariya SIZMAZ. 9// ð´ #1625 B'de bulunan HATA (PR #1608 regresyonu): bu dosya ve sets/detail.js AYNI sayfada 10// (UserSet/UserSetDetail.cshtml) yuklenir ve IKISI de top-level `const pbUrl` bildiriyordu. 11// Klasik <script>'lerde top-level const/let GLOBAL LEXICAL SCOPE'a girer -- ikinci dosya 12// "SyntaxError: Identifier 'pbUrl' has already been declared" ile TAMAMEN parse edilemiyordu, 13// yani UserSetDetail sayfasinda SetDetailManager (filtre/siralama/toplu islem/adet stepper) 14// HIC calismiyordu. Ad burada benzersizlestirildi. 15// Regresyon testi: Croone.TCGSepeti.Tests/JsRuntime/tests/userset-detail-script-collision.test.js 16const usDetailPbUrl = (function () { 17 return function usDetailPbUrl(path) { 18 return ((document.body && document.body.dataset.pathbase) || '') + path; 19 }; 20})(); 21 22// ---- i18n (Issue #1625 B, icerik sayfalari dilimi) ---------------------------------- 23// Kullaniciya gorunen metinler artik bu dosyada SABIT DEGIL: UserSetDetail.cshtml'in 24// .ct-hero kokune data-i18n-* attribute'lari basar, sunucu onlari UserSetDetail.resx / 25// UserSetDetail.en.resx'ten doldurur. Ayni desen basket.js (#1625 B ilk dilim) / 26// destek.js (#1613). Attribute yoksa (or. onbellekten gelen eski HTML) bugunku TR metne 27// duseriz -- davranis degismez. IIFE: usDetailPbUrl ile ayni gerekce (global sizinti olmasin). 28const usDetailI18n = (function () { 29 const root = document.querySelector('.ct-hero[data-i18n-confirm-remove-card]'); 30 return { 31 t: function (name, fallback) { 32 if (!root) return fallback; 33 const value = root.getAttribute('data-i18n-' + name); 34 return (value === null || value === '') ? fallback : value; 35 }, 36 /** '{0}' yer tutucusunu argumanlarla degistirir (basket.js fmt() ile ayni sozlesme). */ 37 fmt: function (template) { 38 const args = Array.prototype.slice.call(arguments, 1); 39 return String(template == null ? '' : template).replace(/\{(\d+)\}/g, function (match, index) { 40 const v = args[Number(index)]; 41 return v === undefined ? match : v; 42 }); 43 } 44 }; 45})(); 46 47// Handle delete card from user set button clicks with event delegation 48document.addEventListener('DOMContentLoaded', function() { 49 // Use event delegation for delete buttons 50 document.addEventListener('click', function(e) { 51 const btn = e.target.closest('.card-delete-btn'); 52 if (!btn) return; 53 54 e.preventDefault(); 55 e.stopPropagation(); 56 57 handleDeleteCardClick(btn); 58 }); 59}); 60 61function handleDeleteCardClick(btn) { 62 const cardId = parseInt(btn.getAttribute('data-card-id') || '0'); 63 const userSetId = parseInt(btn.getAttribute('data-user-set-id') || '0'); 64 65 if (isNaN(cardId) || isNaN(userSetId)) { 66 console.error('Invalid card ID or user set ID'); 67 alert(usDetailI18n.t('invalid-card-or-set-id', 'Hata: Geçersiz kart veya set kimliÄi')); 68 return; 69 } 70 71 // Confirm deletion 72 if (!confirm(usDetailI18n.t('confirm-remove-card', 'Bu kartı setten çıkarmak istediÄinizden emin misiniz?'))) { 73 return; 74 } 75 76 const csrfToken = getCsrfToken(); 77 78 if (!csrfToken) { 79 console.error('CSRF token not found'); 80 alert(usDetailI18n.t('csrf-missing', 'Güvenlik token bulunamadı. Lütfen sayfayı yenile ve tekrar deneyin.')); 81 return; 82 } 83 84 // Disable button temporarily 85 btn.disabled = true; 86 const originalContent = btn.innerHTML; 87 btn.innerHTML = '<i class="bi bi-hourglass-split"></i>'; 88 89 const formData = new FormData(); 90 formData.append('userSetId', userSetId); 91 formData.append('cardIds', JSON.stringify([cardId])); 92 formData.append('__RequestVerificationToken', csrfToken); 93 94 fetch(usDetailPbUrl('/Sets/RemoveCardsFromUserSet'), { 95 method: 'POST', 96 body: formData, 97 headers: { 'X-Requested-With': 'XMLHttpRequest' } 98 }) 99 .then(response => { 100 console.log('Response status:', response.status); 101 102 if (!response.ok) { 103 throw new Error('HTTP error, status = ' + response.status); 104 } 105 return response.json(); 106 }) 107 .then(data => { 108 if (data.success) { 109 // Remove the card from the DOM with animation 110 const cardElement = btn.closest('.single-card'); 111 if (cardElement) { 112 cardElement.style.transition = 'opacity 0.3s ease'; 113 cardElement.style.opacity = '0'; 114 setTimeout(() => { 115 cardElement.remove(); 116 117 // Check if there are any cards left 118 const remainingCards = document.querySelectorAll('.single-card'); 119 if (remainingCards.length === 0) { 120 // Reload page to show "no cards" message 121 location.reload(); 122 } 123 }, 300); 124 } 125 126 // Show success message 127 showNotification(usDetailI18n.t('card-removed', 'Kart setten baÅarıyla çıkarıldı'), 'success'); 128 } else { 129 const errorMsg = usDetailI18n.fmt( 130 usDetailI18n.t('error-format', 'Hata: {0}'), 131 data.message || usDetailI18n.t('unknown-error', 'Bilinmeyen hata')); 132 console.error(errorMsg); 133 alert(errorMsg); 134 btn.disabled = false;
135 btn.innerHTML = originalContent; 136 } 137 }) 138 .catch(error => { 139 console.error('Error:', error); 140 alert(usDetailI18n.fmt(usDetailI18n.t('unexpected-error-format', 'Bir hata oluÅtu: {0}'), error.message)); 141 btn.disabled = false; 142 btn.innerHTML = originalContent; 143 }); 144} 145 146function getCsrfToken() { 147 // Try to get from input field first (most reliable) 148 let token = document.getElementById('csrf-token-input')?.value; 149 150 // If not found, try to get from any input with this name 151 if (!token) { 152 token = document.querySelector('input[name="__RequestVerificationToken"]')?.value; 153 } 154 155 // If still not found, try meta tag 156 if (!token) { 157 token = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); 158 } 159 160 return token || null; 161} 162 163function showNotification(message, type) { 164 type = type || 'info'; 165 166 const alertBox = document.getElementById('alertBox'); 167 const alertMessage = document.getElementById('alertMessage'); 168 169 if (!alertBox || !alertMessage) { 170 return; 171 } 172 173 // Set message 174 alertMessage.textContent = message; 175 176 // Remove all background classes 177 alertBox.classList.remove('bg-success', 'bg-danger', 'bg-info', 'bg-warning', 'text-bg-primary', 'text-bg-success', 'text-bg-danger', 'text-bg-warning'); 178 179 // Add appropriate class based on type 180 switch (type) { 181 case 'success': 182 alertBox.classList.add('bg-success', 'text-white'); 183 break; 184 case 'error': 185 alertBox.classList.add('bg-danger', 'text-white'); 186 break; 187 case 'warning': 188 alertBox.classList.add('bg-warning', 'text-dark'); 189 break; 190 default: 191 alertBox.classList.add('bg-info', 'text-white'); 192 } 193 194 // Show toast using Bootstrap 195 const toast = new bootstrap.Toast(alertBox); 196 toast.show(); 197}
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.