/**
* @module scripts
* @description
* Contains main application logic, global event listeners, and utility functions.
* Coordinates interactions between modules and manages app-wide behaviors.
*/
let currentSection = "home";
const sections = document.querySelectorAll(".section");
const navLinks = document.querySelectorAll(".nav-link");
const searchInput = document.getElementById("searchInput");
const modal = document.getElementById("modal");
const videoModal = document.getElementById("videoModal");
const videoPlayer = document.getElementById("videoPlayer");
/**
* Sets up all global event listeners for navigation, filtering, modals, video tracking, and search.
*
* @function
* @returns {void}
*/
function setupEventListeners() {
navLinks.forEach((link) => {
link.addEventListener("click", (e) => {
e.preventDefault();
const section = link.dataset.section;
showSection(section);
setActiveNavLink(link);
});
});
searchInput.addEventListener("input", debounce(handleSearch, 300));
document.querySelectorAll(".close-btn").forEach((btn) => {
btn.addEventListener("click", closeModals);
});
modal.addEventListener("click", (e) => {
if (e.target === modal) closeModals();
});
videoModal.addEventListener("click", (e) => {
if (e.target === videoModal) closeModals();
});
document.getElementById("filmGenreFilter").addEventListener("change", () => {
displayFilms(getFilteredFilms());
});
document.getElementById("filmYearFilter").addEventListener("change", () => {
displayFilms(getFilteredFilms());
});
document
.getElementById("filmDirectorFilter")
.addEventListener("change", () => {
displayFilms(getFilteredFilms());
});
document.getElementById("filmActorFilter").addEventListener("change", () => {
displayFilms(getFilteredFilms());
});
document.getElementById("filmRatingFilter").addEventListener("input", (e) => {
document.querySelector("#films .rating-value").textContent = parseFloat(e.target.value).toFixed(1);
displayFilms(getFilteredFilms());
});
document
.getElementById("seriesGenreFilter")
.addEventListener("change", () => {
displaySeries(getFilteredSeries());
});
document.getElementById("seriesYearFilter").addEventListener("change", () => {
displaySeries(getFilteredSeries());
});
document
.getElementById("seriesCreatorFilter")
.addEventListener("change", () => {
displaySeries(getFilteredSeries());
});
document
.getElementById("seriesActorFilter")
.addEventListener("change", () => {
displaySeries(getFilteredSeries());
});
document
.getElementById("seriesRatingFilter")
.addEventListener("input", (e) => {
document.querySelector("#series .rating-value").textContent = parseFloat(e.target.value).toFixed(1);
displaySeries(getFilteredSeries());
});
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
closeModals();
}
});
if (videoPlayer) {
videoPlayer.addEventListener("timeupdate", handleVideoTimeUpdate);
videoPlayer.addEventListener("ended", handleVideoEnded);
videoPlayer.addEventListener("pause", handleVideoPause);
}
}
/**
* Shows the specified section and updates content as needed.
*
* @function
* @param {string} sectionName - The name of the section to display.
* @returns {void}
*/
function showSection(sectionName) {
sections.forEach((section) => {
section.classList.remove("active");
});
document.getElementById(sectionName).classList.add("active");
currentSection = sectionName;
switch (sectionName) {
case "films":
displayFilms(Object.values(filmsData));
break;
case "series":
displaySeries(Object.values(seriesData));
break;
case "search":
if (searchInput.value.trim()) {
handleSearch();
}
break;
case "stats":
displayStats();
break;
}
}
/**
* Sets the given navigation link as active and removes active state from others.
*
* @function
* @param {Element} activeLink - The navigation link element to activate.
* @returns {void}
*/
function setActiveNavLink(activeLink) {
navLinks.forEach((link) => link.classList.remove("active"));
activeLink.classList.add("active");
}
/**
* Handles the global error event for images.
*
* Replaces broken images with a fallback icon when an image fails to load.
*
* @event
* @param {Event} e - The error event.
* @returns {void}
*/
document.addEventListener("error", (e) => {
if (e.target.tagName === "IMG") {
e.target.style.display = "none";
e.target.parentElement.innerHTML = '<i class="fas fa-film"></i>';
}
}, true);
/**
* Handles the global keydown event for keyboard shortcuts.
*
* Focuses the search input when the "/" key is pressed (without Ctrl or Alt).
*
* @event
* @param {KeyboardEvent} e - The keydown event.
* @returns {void}
*/
document.addEventListener("keydown", (e) => {
if (e.key === "/" && !e.ctrlKey && !e.altKey) {
e.preventDefault();
searchInput.focus();
}
});