refactor: split CSS and JS into modular files (SRP)
This commit is contained in:
156
src/server/web/static/js/index/search.js
Normal file
156
src/server/web/static/js/index/search.js
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* AniWorld - Search Module
|
||||
*
|
||||
* Handles anime search functionality and result display.
|
||||
*
|
||||
* Dependencies: constants.js, api-client.js, ui-utils.js, series-manager.js
|
||||
*/
|
||||
|
||||
var AniWorld = window.AniWorld || {};
|
||||
|
||||
AniWorld.Search = (function() {
|
||||
'use strict';
|
||||
|
||||
const API = AniWorld.Constants.API;
|
||||
|
||||
/**
|
||||
* Initialize the search module
|
||||
*/
|
||||
function init() {
|
||||
bindEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind UI events
|
||||
*/
|
||||
function bindEvents() {
|
||||
const searchInput = document.getElementById('search-input');
|
||||
const searchBtn = document.getElementById('search-btn');
|
||||
const clearSearch = document.getElementById('clear-search');
|
||||
|
||||
if (searchBtn) {
|
||||
searchBtn.addEventListener('click', performSearch);
|
||||
}
|
||||
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
performSearch();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (clearSearch) {
|
||||
clearSearch.addEventListener('click', function() {
|
||||
if (searchInput) searchInput.value = '';
|
||||
hideSearchResults();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform anime search
|
||||
*/
|
||||
async function performSearch() {
|
||||
const searchInput = document.getElementById('search-input');
|
||||
const query = searchInput ? searchInput.value.trim() : '';
|
||||
|
||||
if (!query) {
|
||||
AniWorld.UI.showToast('Please enter a search term', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
AniWorld.UI.showLoading();
|
||||
|
||||
const response = await AniWorld.ApiClient.post(API.ANIME_SEARCH, { query: query });
|
||||
|
||||
if (!response) return;
|
||||
const data = await response.json();
|
||||
|
||||
// Check if response is a direct array (new format) or wrapped object (legacy)
|
||||
if (Array.isArray(data)) {
|
||||
displaySearchResults(data);
|
||||
} else if (data.status === 'success') {
|
||||
displaySearchResults(data.results);
|
||||
} else {
|
||||
AniWorld.UI.showToast('Search error: ' + (data.message || 'Unknown error'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Search error:', error);
|
||||
AniWorld.UI.showToast('Search failed', 'error');
|
||||
} finally {
|
||||
AniWorld.UI.hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display search results
|
||||
* @param {Array} results - Search results array
|
||||
*/
|
||||
function displaySearchResults(results) {
|
||||
const resultsContainer = document.getElementById('search-results');
|
||||
const resultsList = document.getElementById('search-results-list');
|
||||
|
||||
if (results.length === 0) {
|
||||
resultsContainer.classList.add('hidden');
|
||||
AniWorld.UI.showToast('No search results found', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
resultsList.innerHTML = results.map(function(result) {
|
||||
const displayName = AniWorld.UI.getDisplayName(result);
|
||||
return '<div class="search-result-item">' +
|
||||
'<span class="search-result-name">' + AniWorld.UI.escapeHtml(displayName) + '</span>' +
|
||||
'<button class="btn btn-small btn-primary" ' +
|
||||
'onclick="AniWorld.Search.addSeries(\'' + AniWorld.UI.escapeHtml(result.link) + '\', \'' +
|
||||
AniWorld.UI.escapeHtml(displayName) + '\')">' +
|
||||
'<i class="fas fa-plus"></i> Add' +
|
||||
'</button>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
|
||||
resultsContainer.classList.remove('hidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide search results
|
||||
*/
|
||||
function hideSearchResults() {
|
||||
document.getElementById('search-results').classList.add('hidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a series from search results
|
||||
* @param {string} link - Series link
|
||||
* @param {string} name - Series name
|
||||
*/
|
||||
async function addSeries(link, name) {
|
||||
try {
|
||||
const response = await AniWorld.ApiClient.post(API.ANIME_ADD, { link: link, name: name });
|
||||
|
||||
if (!response) return;
|
||||
const data = await response.json();
|
||||
|
||||
if (data.status === 'success') {
|
||||
AniWorld.UI.showToast(data.message, 'success');
|
||||
AniWorld.SeriesManager.loadSeries();
|
||||
hideSearchResults();
|
||||
document.getElementById('search-input').value = '';
|
||||
} else {
|
||||
AniWorld.UI.showToast('Error adding series: ' + data.message, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error adding series:', error);
|
||||
AniWorld.UI.showToast('Failed to add series', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Public API
|
||||
return {
|
||||
init: init,
|
||||
performSearch: performSearch,
|
||||
hideSearchResults: hideSearchResults,
|
||||
addSeries: addSeries
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user