PageSourceSearch

https://novashow.live/tvshows.js

js novashow.live collected 2026-10-10 02:21:50 UTC 5,025 bytes, 140 lines download raw bytes

1const API_KEY = '603b3a029ec4f3222d788b8de4945dba';
2let currentPage = 1;
3let currentGenre = '';
4let currentYear = '';
5let currentSort = 'popularity.desc';
6let isLoading = false;
7
8document.addEventListener('DOMContentLoaded', () => {
9    initializeFilters();
10    loadTVShows();
11    setupLoadMore();
12});
13
14async function initializeFilters() {
15    // Load genres
16    try {
17        const response = await fetch(`https://api.themoviedb.org/3/genre/tv/list?api_key=${API_KEY}`);
18        const data = await response.json();
19        const genreSelect = document.getElementById('genre-filter');
20        
21        data.genres.forEach(genre => {
22            const option = document.createElement('option');
23            option.value = genre.id;
24            option.textContent = genre.name;
25            option.className = 'dark-option';
26            genreSelect.appendChild(option);
27        });
28    } catch (error) {
29        console.error('Error loading genres:', error);
30    }
31
32    // Generate years (current year - 50 years)
33    const yearSelect = document.getElementById('year-filter');
34    const currentYear = new Date().getFullYear();
35    for (let year = currentYear; year >= currentYear - 50; year--) {
36        const option = document.createElement('option');
37        option.value = year;
38        option.textContent = year;
39        option.className = 'dark-option';
40        yearSelect.appendChild(option);
41    }
42
43    // Add dark option class to sort filter options
44    document.querySelectorAll('#sort-filter option').forEach(option => {
45        option.className = 'dark-option';
46    });
47
48    // Add event listeners
49    document.getElementById('genre-filter').addEventListener('change', handleFilterChange);
50    document.getElementById('year-filter').addEventListener('change', handleFilterChange);
51    document.getElementById('sort-filter').addEventListener('change', handleFilterChange);
52}
53
54function handleFilterChange() {
55    currentGenre = document.getElementById('genre-filter').value;
56    currentYear = document.getElementById('year-filter').value;
57    currentSort = document.getElementById('sort-filter').value;
58    currentPage = 1;
59    loadTVShows(true);
60}
61
62async function loadTVShows(reset = false) {
63    if (isLoading) return;
64    isLoading = true;
65
66    const tvShowsGrid = document.querySelector('.movies-grid');
67    if (reset) {
68        tvShowsGrid.innerHTML = '<div class="loading">Loading TV shows...</div>';
69    }
70
71    try {
72        let url = `https://api.themoviedb.org/3/discover/tv?api_key=${API_KEY}&language=en-US&page=${currentPage}&sort_by=${currentSort}`;
73        
74        if (currentGenre) {
75            url += `&with_genres=${currentGenre}`;
76        }
77        if (currentYear) {
78            url += `&first_air_date_year=${currentYear}`;
79        }
80
81        const response = await fetch(url);
82        const data = await response.json();
83
84        if (reset) {
85            tvShowsGrid.innerHTML = '';
86        }
87
88        data.results.forEach(show => {
89            const showCard = document.createElement('div');
90            showCard.className = 'movie-card';
91            showCard.innerHTML = `
92                <div class="card-image">
93                    <img src="https://image.tmdb.org/t/p/w342${show.poster_path}" width="342" height="513"
94                         loading="lazy" decoding="async"
95                         alt="${show.name}"
96                         onerror="this.src='placeholder.jpg'">
97                    <div class="card-overlay">
98                        <div class="rating">
99                            <i class="fas fa-star"></i>
100                            <span>${show.vote_average.toFixed(1)}</span>
101                        </div>
102                        <p>${show.overview ? show.overview.slice(0, 100) + '...' : 'No overview available'}</p>
103                    </div>
104                </div>
105                <div class="card-info">
106                    <h4>${show.name}</h4>
107                    <div class="meta">
108                        <span>${show.first_air_date ? show.first_air_date.split('-')[0] : 'N/A'}</span>
109                        <span>${show.original_language.toUpperCase()}</span>
110                    </div>
111                </div>
112            `;
113
114            showCard.addEventListener('click', () => {
115                window.location.href = `/details?id=${show.id}&type=tv`;
116            });
117
118            tvShowsGrid.appendChild(showCard);
119        });
120
121        isLoading = false;
122        document.getElementById('load-more-btn').style.display = 
123            currentPage >= data.total_pages ? 'none' : 'inline-block';
124
125    } catch (error) {
126        console.error('Error loading TV shows:', error);
127        if (reset) {
128            tvShowsGrid.innerHTML = '<div class="error">Error loading TV shows. Please try again later.</div>';
129        }
130        isLoading = false;
131    }
132}
133
134function setupLoadMore() {
135    const loadMoreBtn = document.getElementById('load-more-btn');
136    loadMoreBtn.addEventListener('click', () => {
137        currentPage++;
138        loadTVShows();
139    });
140}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.