Spaces:
Sleeping
Sleeping
| document.addEventListener('DOMContentLoaded', () => { | |
| // DOM Elements | |
| const searchForm = document.getElementById('searchForm'); | |
| const queryInput = document.getElementById('queryInput'); | |
| const searchBtn = document.getElementById('searchBtn'); | |
| const searchIcon = document.getElementById('searchIcon'); | |
| const loadingSpinner = document.getElementById('loadingSpinner'); | |
| const topKInput = document.getElementById('topKInput'); | |
| const topKValue = document.getElementById('topKValue'); | |
| const resultsContainer = document.getElementById('resultsContainer'); | |
| const errorMsg = document.getElementById('errorMsg'); | |
| const noResults = document.getElementById('noResults'); | |
| // Update Slider Value | |
| topKInput.addEventListener('input', (e) => { | |
| topKValue.textContent = e.target.value; | |
| }); | |
| // Form Submit | |
| searchForm.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| const query = queryInput.value.trim(); | |
| if (!query) return; | |
| const topK = parseInt(topKInput.value); | |
| // UI Loading State | |
| setLoading(true); | |
| hideElements([errorMsg, noResults]); | |
| resultsContainer.innerHTML = ''; | |
| try { | |
| const response = await fetch('/api/search', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ query, top_k: topK }) | |
| }); | |
| if (!response.ok) { | |
| const contentType = response.headers.get("content-type"); | |
| if (contentType && contentType.includes("application/json")) { | |
| const errData = await response.json(); | |
| throw new Error(errData.detail || 'حدث خطأ أثناء الاتصال بالخادم'); | |
| } else { | |
| const text = await response.text(); | |
| console.error("Non-JSON Server Error:", text); | |
| if (response.status === 504 || response.status === 503) { | |
| throw new Error("تأخر الخادم في الاستجابة (جاري تهيئة مساحة HuggingFace). يرجى المحاولة مرة أخرى."); | |
| } | |
| throw new Error(`خطأ في الخادم (الكود ${response.status}) - يرجى الانتظار والمحاولة لاحقاً.`); | |
| } | |
| } | |
| const data = await response.json(); | |
| const results = data.results || []; | |
| if (results.length === 0) { | |
| noResults.classList.remove('hidden'); | |
| } else { | |
| renderResults(results); | |
| } | |
| } catch (error) { | |
| showError(error.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }); | |
| function renderResults(results) { | |
| results.forEach((result, index) => { | |
| const delay = index * 0.15; // Staggered animation | |
| const card = document.createElement('div'); | |
| card.className = 'result-card'; | |
| card.style.animationDelay = `${delay}s`; | |
| // Topic badge (if exists) | |
| const topicHtml = result.topic && result.topic !== "nan" | |
| ? `<span class="badge badge-topic">${result.topic}</span>` | |
| : ''; | |
| // Source URL link (if exists) | |
| const sourceHtml = result.source_url && result.source_url !== "nan" | |
| ? `<a href="${result.source_url}" target="_blank" class="text-gold" style="font-size: 0.9rem; margin-right: 15px;">🔗 المصدر</a>` | |
| : ''; | |
| card.innerHTML = ` | |
| <div class="result-header"> | |
| <span class="result-title">${result.title || 'حديث غير معنون'}</span> | |
| ${topicHtml} | |
| ${sourceHtml} | |
| <span class="badge-rank">#${result.rank || (index + 1)}</span> | |
| </div> | |
| <div class="result-text">${highlightQuery(result.text, queryInput.value)}</div> | |
| `; | |
| resultsContainer.appendChild(card); | |
| }); | |
| } | |
| // Basic highlighter for UX (optional enhancement) | |
| function highlightQuery(text, query) { | |
| if (!text) return ''; | |
| // Very basic escaping text to prevent XSS | |
| return text.replace(/</g, "<").replace(/>/g, ">"); | |
| } | |
| function setLoading(isLoading) { | |
| if (isLoading) { | |
| searchBtn.disabled = true; | |
| searchIcon.classList.add('hidden'); | |
| loadingSpinner.classList.remove('hidden'); | |
| } else { | |
| searchBtn.disabled = false; | |
| loadingSpinner.classList.add('hidden'); | |
| searchIcon.classList.remove('hidden'); | |
| } | |
| } | |
| function showError(message) { | |
| errorMsg.textContent = message; | |
| errorMsg.classList.remove('hidden'); | |
| } | |
| function hideElements(elements) { | |
| elements.forEach(el => el.classList.add('hidden')); | |
| } | |
| }); | |