Hadith_Search / assets /script.js
NightPrince's picture
Hotfix: Pre-load HF Model and Fix HTML Error Responses
97250e9
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, "&lt;").replace(/>/g, "&gt;");
}
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'));
}
});