Elementor #31995

Prêt.
`; } async function openCinemaView() { if (currentResults.length === 0) { alert("Aucun film à afficher. Lancez d'abord une recherche."); return; } const win = window.open("", "_blank"); if (!win) { alert("Merci d'autoriser les fenêtres pop-up pour ce site afin d'ouvrir la vue cinéma."); return; } win.document.open(); win.document.write(renderCinemaHtml(currentResults, [], true)); win.document.close(); let upcomingFilms = []; try { const listData = await fetchWikidataOnce(buildUpcomingListQuery(UPCOMING_LIMIT)); const rows = listData.results.bindings; if (rows.length) { const uris = rows.map(row => row.item.value); const detailsData = await fetchWikidataOnce(buildDetailsQuery(uris)); const detailsByUri = {}; detailsData.results.bindings.forEach(row => { detailsByUri[row.item.value] = row; }); upcomingFilms = rows.map(row => convertResult(row, detailsByUri[row.item.value])); } } catch (error) { console.warn("Films à venir indisponibles :", error); } if (!win.closed) { win.document.open(); win.document.write(renderCinemaHtml(currentResults, upcomingFilms, false)); win.document.close(); } } /* ========================================================= EVENEMENTS ========================================================= */ cancelButton.addEventListener("click", function () { if (abortController) abortController.abort(); }); document.getElementById("wdfc-searchButton").addEventListener("click", function () { currentPage = 1; searchWikidata(); }); searchInput.addEventListener("keydown", function (event) { if (event.key === "Enter") { currentPage = 1; searchWikidata(); } }); nextButton.addEventListener("click", function () { if (currentPage < totalPages) { currentPage++; searchWikidata(); } }); previousButton.addEventListener("click", function () { if (currentPage > 1) { currentPage--; searchWikidata(); } }); document.getElementById("wdfc-pageButton").addEventListener("click", function () { let page = Number(pageInput.value); if (page < 1) page = 1; if (totalKnown && page > totalPages) page = totalPages; currentPage = page; searchWikidata(); }); document.getElementById("wdfc-reloadButton").addEventListener("click", searchWikidata); allLanguagesCheckbox.addEventListener("change", function () { languageOptionsContainer.classList.toggle("is-disabled", allLanguagesCheckbox.checked); }); destinationSiteSelect.addEventListener("change", function () { customSiteUrlInput.disabled = destinationSiteSelect.value !== "custom"; if (currentResults.length) renderResults(); }); const TITLE_COLOR_STORAGE_KEY = "wdfcFilmCatalogTitleColor"; titleColorPicker.addEventListener("input", function () { document.querySelector(".wdfc-app").style.setProperty("--wdfc-title-color", titleColorPicker.value); try { localStorage.setItem(TITLE_COLOR_STORAGE_KEY, titleColorPicker.value); } catch (error) { console.warn("Impossible de sauvegarder la couleur choisie :", error); } }); customSiteUrlInput.addEventListener("input", function () { if (destinationSiteSelect.value === "custom" && currentResults.length) { renderResults(); } }); youtubeButton.addEventListener("click", function () { if (currentResults.length === 0) { alert("Aucun film à afficher pour le moment. Lancez d'abord une recherche."); return; } const win = window.open("", "_blank"); if (!win) { alert("Merci d'autoriser les fenêtres pop-up pour ce site afin d'ouvrir la sélection YouTube."); return; } const linksHtml = currentResults.map(film => { const title = film.title || "Titre non renseigné"; const query = encodeURIComponent(title + " film complet"); const url = "https://www.youtube.com/results?search_query=" + query; return "
  • " + escapeHTML(title) + "
  • "; }).join(""); win.document.write( "" + "Sélection sur YouTube" + "" + "

    🎬 Recherche YouTube — sélection actuelle (" + currentResults.length + " film(s))

    " + "
      " + linksHtml + "
    " ); win.document.close(); }); cinemaButton.addEventListener("click", openCinemaView); document.getElementById("wdfc-resetButton").addEventListener("click", function () { if (isLoading && abortController) abortController.abort(); searchInput.value = ""; searchCategory.value = "title"; destinationSiteSelect.value = "justwatch"; customSiteUrlInput.value = ""; customSiteUrlInput.disabled = true; dayInput.value = ""; monthInput.value = ""; yearInput.value = ""; yearFromInput.value = ""; yearToInput.value = ""; dateFromInput.value = ""; dateToInput.value = ""; titleFilter.value = "all"; dateFilter.value = "all"; typeFilter.value = "film_animation"; document.querySelectorAll(".wdfc-languageCheckbox").forEach(cb => { cb.checked = (cb.value === "fr"); }); allLanguagesCheckbox.checked = false; languageOptionsContainer.classList.remove("is-disabled"); religiousFilter.checked = true; document.querySelectorAll(".wdfc-lexicalKeyword").forEach(cb => { cb.checked = false; }); lexicalCustomInput.value = ""; excludeWordsInput.value = ""; sortSelect.value = "newest"; pageSizeSelect.value = "20"; maxResultsInput.value = ""; currentPage = 1; totalPages = 1; totalKnown = true; hasNextPageUnknown = false; currentResults = []; resultsElement.innerHTML = ""; progressBar.style.width = "0%"; pageInput.value = 1; pageInfo.textContent = "Page 1 / 1"; statusElement.textContent = "Filtres réinitialisés."; }); document.getElementById("wdfc-exportButton").addEventListener("click", function () { if (currentResults.length === 0) { alert("Aucun résultat à exporter."); return; } const header = ["Titre", "Réalisateur(s)", "Casting", "Date", "Lien", "Wikidata", "Source"]; const rows = currentResults.map(film => [ film.title, film.directors, film.cast, film.date, film.primaryLink, film.uri, film.source ]); const csv = [header, ...rows] .map(row => row.map(value => '"' + String(value || "").replace(/"/g, '""') + '"' ).join(";")) .join("\n"); const blob = new Blob(["\ufeff" + csv], { type: "text/csv;charset=utf-8" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = "films-wikidata.csv"; link.click(); URL.revokeObjectURL(url); }); /* ========================================================= INITIALISATION ========================================================= */ statusElement.textContent = "Prêt. Entrez un terme ou lancez une recherche."; loadAvailableLanguages(); try { const savedTitleColor = localStorage.getItem(TITLE_COLOR_STORAGE_KEY); if (savedTitleColor) { titleColorPicker.value = savedTitleColor; document.querySelector(".wdfc-app").style.setProperty("--wdfc-title-color", savedTitleColor); } } catch (error) { console.warn("Impossible de relire la couleur sauvegardée :", error); } /* ========================================================================================= MODULE TMDB - PLUS DE FILMS CHRETIENS (imbriqué ici pour partager le scope avec le reste du script — currentResults, renderResults, etc. restent accessibles sans passer par window global) ========================================================================================= */ (function () { "use strict"; const TMDB_API_KEY = "af5576c58fe6fd7fab447fbb4dd2423a"; const TMDB_API = "https://api.themoviedb.org/3"; const TMDB_LANGUAGE = "fr-FR"; const TMDB_REGION = "FR"; const TMDB_MAX_PAGES = 500; const CHRISTIAN_KEYWORDS = [ "christianity", "christian", "christian faith", "christian film", "religious film", "religion", "faith", "bible", "biblical", "jesus christ", "jesus", "gospel", "resurrection", "crucifixion", "church", "evangelical christianity" ]; const typeFilterEl = document.getElementById("wdfc-typeFilter"); const pageSizeSelectEl = document.getElementById("wdfc-pageSize"); const maxResultsInputEl = document.getElementById("wdfc-maxResults"); const sortSelectEl = document.getElementById("wdfc-sort"); const religiousFilterEl = document.getElementById("wdfc-religiousFilter"); const allLanguagesCheckboxEl = document.getElementById("wdfc-allLanguages"); const languageOptionsContainerEl = document.getElementById("wdfc-languageOptions"); const statusElementEl = document.getElementById("wdfc-status"); const progressBarEl = document.getElementById("wdfc-progressBar"); const resultsElementEl = document.getElementById("wdfc-results"); if (!typeFilterEl || !pageSizeSelectEl || !maxResultsInputEl || !sortSelectEl) { console.warn("TMDB Plus : un ou plusieurs filtres nécessaires sont absents."); return; } function createTMDBButton() { if (document.getElementById("wdfc-tmdbPlusButton")) return; const button = document.createElement("button"); button.id = "wdfc-tmdbPlusButton"; button.type = "button"; button.textContent = "🎬 Plus de films"; const searchButtonEl = document.querySelector( '#wdfc-searchButton, [data-action="search"], button[type="submit"]' ); if (searchButtonEl && searchButtonEl.parentNode) { searchButtonEl.parentNode.appendChild(button); } else if (resultsElementEl && resultsElementEl.parentNode) { resultsElementEl.parentNode.insertBefore(button, resultsElementEl); } else { document.body.appendChild(button); } const status = document.createElement("div"); status.id = "wdfc-tmdbPlusStatus"; if (button.parentNode) { button.parentNode.insertBefore(status, button.nextSibling); } button.addEventListener("click", function () { searchTMDB(); }); } function setTMDBStatus(message) { const element = document.getElementById("wdfc-tmdbPlusStatus"); if (element) { element.textContent = message; element.style.display = "block"; } if (statusElementEl) { statusElementEl.textContent = message; } } function normalizeTitle(value) { return String(value || "") .toLowerCase() .normalize("NFD") .replace(/[\u0300-\u036f]/g, "") .replace(/[^\p{L}\p{N}]+/gu, " ") .trim(); } function getYear(value) { if (!value) return ""; const match = String(value).match(/\b(18|19|20)\d{2}\b/); return match ? match[0] : ""; } function getTMDBType() { const value = typeFilterEl.value; if (value === "film") return ["movie"]; if (value === "animation") return ["animation"]; if (value === "film_animation") return ["movie", "animation"]; if (value === "all") return ["movie", "animation"]; return ["movie"]; } function getSelectedLanguagesTMDB() { if (allLanguagesCheckboxEl && allLanguagesCheckboxEl.checked) return []; if (!languageOptionsContainerEl) return []; const checked = languageOptionsContainerEl.querySelectorAll('input[type="checkbox"]:checked'); const languages = []; checked.forEach(function (checkbox) { const language = checkbox.value || checkbox.dataset.lang || checkbox.dataset.language || ""; if (language) languages.push(language.toLowerCase()); }); return [...new Set(languages)]; } async function findKeywordId(keyword) { const params = new URLSearchParams({ api_key: TMDB_API_KEY, query: keyword, page: "1" }); const response = await fetch(TMDB_API + "/search/keyword?" + params.toString()); if (!response.ok) throw new Error("Recherche de mot-clé TMDB : HTTP " + response.status); const data = await response.json(); if (!data.results || !data.results.length) return null; const exact = data.results.find(function (item) { return normalizeTitle(item.name) === normalizeTitle(keyword); }); return (exact || data.results[0]).id; } async function getKeywordIds() { const results = await Promise.all( CHRISTIAN_KEYWORDS.map(function (keyword) { return findKeywordId(keyword).catch(function (error) { console.warn("Mot-clé ignoré :", keyword, error); return null; }); }) ); return [...new Set(results.filter(Boolean))]; } async function fetchTMDBPage(keywordId, page, animationOnly) { const params = new URLSearchParams({ api_key: TMDB_API_KEY, language: TMDB_LANGUAGE, region: TMDB_REGION, with_keywords: String(keywordId), sort_by: "primary_release_date.desc", include_adult: "false", page: String(page) }); if (animationOnly) params.set("with_genres", "16"); const response = await fetch(TMDB_API + "/discover/movie?" + params.toString()); if (!response.ok) throw new Error("TMDB Discover : HTTP " + response.status); return await response.json(); } function matchesLanguage(movie, languages) { if (!languages.length) return true; const originalLanguage = String(movie.original_language || "").toLowerCase(); return languages.includes(originalLanguage); } function isExistingResult(movie) { if (!Array.isArray(currentResults)) return false; const tmdbId = String(movie.id); const title = normalizeTitle(movie.title || movie.original_title); const year = getYear(movie.release_date); return currentResults.some(function (existing) { if (existing.tmdbId && String(existing.tmdbId) === tmdbId) return true; const existingTitle = normalizeTitle(existing.title); const existingYear = getYear(existing.date || existing.year || existing.release_date); if (title && existingTitle && title === existingTitle && year && existingYear && year === existingYear) return true; if (title && existingTitle && title === existingTitle && (!year || !existingYear)) return true; return false; }); } function convertTMDBResult(movie) { const title = movie.title || movie.original_title || "Titre non renseigné"; return { uri: "tmdb:" + movie.id, title: title, poster: "", image: "", directors: "", cast: "", actors: "", date: movie.release_date || "", year: getYear(movie.release_date), description: movie.overview || "", imdb: "", website: "", primaryLink: "https://www.themoviedb.org/movie/" + movie.id, tmdbId: String(movie.id), source: "TMDB", isTMDB: true }; } async function collectTMDBResults() { const selectedTypes = getTMDBType(); const languages = getSelectedLanguagesTMDB(); const maxRaw = maxResultsInputEl.value.trim(); const maxResults = maxRaw ? Math.max(1, Number(maxRaw)) : null; const target = maxResults || Infinity; const keywordIds = await getKeywordIds(); if (!keywordIds.length) { throw new Error("Aucun mot-clé chrétien reconnu par TMDB."); } const unique = new Map(); for (const type of selectedTypes) { const animationOnly = type === "animation"; for (const keywordId of keywordIds) { let page = 1; let totalPages = 1; do { if (unique.size >= target) break; setTMDBStatus( "⏳ TMDB : recherche " + type + " — mot-clé " + keywordId + " — page " + page + " / " + totalPages ); const data = await fetchTMDBPage(keywordId, page, animationOnly); totalPages = Math.min(Number(data.total_pages || 1), TMDB_MAX_PAGES); const results = data.results || []; results.forEach(function (movie) { if (!matchesLanguage(movie, languages)) return; const title = normalizeTitle(movie.title || movie.original_title); const year = getYear(movie.release_date); const key = title + "|" + year; if (!unique.has(key)) unique.set(key, movie); }); page++; if (maxResults && unique.size >= maxResults) break; } while (page <= totalPages); } } let movies = Array.from(unique.values()); if (sortSelectEl.value === "oldest") { movies.sort(function (a, b) { return String(a.release_date || "").localeCompare(String(b.release_date || "")); }); } else if (sortSelectEl.value === "title") { movies.sort(function (a, b) { return normalizeTitle(a.title).localeCompare(normalizeTitle(b.title)); }); } else { movies.sort(function (a, b) { return String(b.release_date || "").localeCompare(String(a.release_date || "")); }); } if (maxResults) movies = movies.slice(0, maxResults); return movies; } async function searchTMDB() { const button = document.getElementById("wdfc-tmdbPlusButton"); if (button.disabled) return; if (religiousFilterEl && !religiousFilterEl.checked) { const proceed = confirm( "Le filtre « Films chrétiens / religieux » est désactivé.\n\n" + "La recherche TMDB de ce bouton est spécialement conçue " + "pour les films chrétiens et religieux.\n\n" + "Voulez-vous continuer ?" ); if (!proceed) return; } button.disabled = true; if (progressBarEl) progressBarEl.style.width = "10%"; try { setTMDBStatus("⏳ Préparation de la recherche TMDB..."); const movies = await collectTMDBResults(); if (progressBarEl) progressBarEl.style.width = "70%"; let added = 0; let duplicates = 0; movies.forEach(function (movie) { if (isExistingResult(movie)) { duplicates++; return; } const converted = convertTMDBResult(movie); currentResults.push(converted); added++; }); if (sortSelectEl.value === "title") { currentResults.sort(function (a, b) { return normalizeTitle(a.title).localeCompare(normalizeTitle(b.title)); }); } else if (sortSelectEl.value === "oldest") { currentResults.sort(function (a, b) { return String(a.date || "").localeCompare(String(b.date || "")); }); } else { currentResults.sort(function (a, b) { return String(b.date || "").localeCompare(String(a.date || "")); }); } if (typeof renderResults === "function") renderResults(); if (progressBarEl) progressBarEl.style.width = "100%"; setTMDBStatus( "✅ TMDB terminé : " + added + " nouveau(x) film(s) ajouté(s). " + duplicates + " doublon(s) ignoré(s)." ); } catch (error) { console.error("TMDB Plus :", error); setTMDBStatus("❌ Erreur TMDB : " + error.message); if (progressBarEl) progressBarEl.style.width = "100%"; } finally { button.disabled = false; } } createTMDBButton(); console.log("✅ Module TMDB « Plus de films » chargé."); })(); } // fin de init() if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } })();
    Retour en haut