/**
* CinemaClock Movie List Handler
* Improved implementation for handling movie list filtering and display
*/
// Movie data model - centralized data structure
const MovieListManager = {
// Core data
data: {
cinemas: {}, // Cinema IDs within selected radius
movies: {}, // All movie data indexed by ID
dates: [], // Available dates
selectedDates: [], // User selected dates
showOnlyFavorites: false, // Show only favorites toggle state
},
// Filter states
filters: {
genres: {}, // {genreCode: true/false}
languages: {}, // {languageCode: true/false}
classifications: {}, // {classificationCode: true/false}
special: {
parentsBabies: false,
sensoryFriendly: false,
withCaptions: false,
withAudioDescription: false
}
},
// Sort preferences
sorting: {
currentSort: 'alpha', // 'alpha', 'value', or 'date'
sortMaps: {
alpha: [], // Movie IDs ordered alphabetically
value: [], // Movie IDs ordered by value/rating
date: [] // Movie IDs ordered by release date
}
},
// Initialize the manager
init: function() {
this.loadDataFromDOM();
this.loadUserPreferences();
this.setupEventListeners();
this.applyFiltersAndUpdate();
},
// Load all necessary data from DOM and variables
loadDataFromDOM: function() {
// Load dates
const uniqueDatesString = sessionStorage.getItem('ccnpdates');
this.data.dates = uniqueDatesString ? JSON.parse(uniqueDatesString) : [];
// Check if dates are valid, if not, use the initial dates
if (!this.data.dates.length) {
this.data.dates = Array.from(datesWeek);
sessionStorage.setItem('ccnpdates', JSON.stringify(this.data.dates));
}
this.data.selectedDates = [...this.data.dates];
// Load cinemas based on selected radius
const ccradtids = localStorage.getItem('ccradtids');
if (ccradtids) {
const cinemaIds = JSON.parse(ccradtids).map(item => parseInt(item, 10));
cinemaIds.forEach(id => this.data.cinemas[id] = true);
}
// Load sort maps
this.sorting.sortMaps.alpha = this.processMovieIds(moviesalpha);
this.sorting.sortMaps.value = this.processMovieIds(moviesval);
this.sorting.sortMaps.date = this.processMovieIds(moviesdate);
// Index movies and their features from DOM elements
document.querySelectorAll('.movieblock').forEach(movieBlock => {
const movieId = movieBlock.id.replace('efilm', '');
const genres = Array.from(movieBlock.classList)
.filter(cls => cls.startsWith('gen'))
.map(cls => cls.replace('gen', ''));
const languages = Array.from(movieBlock.classList)
.filter(cls => languageclasses.includes(cls));
const classifications = Array.from(movieBlock.classList)
.filter(cls => cls.startsWith('r'));
const specialFeatures = {
parentsBabies: movieBlock.classList.contains('genbab'),
sensoryFriendly: movieBlock.classList.contains('gensen'),
withCaptions: movieBlock.classList.contains('gencap'), // Placeholder, need to be added
withAudioDescription: movieBlock.classList.contains('genad') // Placeholder, need to be added
};
// Store movie data
this.data.movies[movieId] = {
id: movieId,
element: movieBlock,
genres: genres,
languages: languages,
classifications: classifications,
specialFeatures: specialFeatures,
showingDates: this.getMovieShowingDates(movieId)
};
});
},
// Get all dates a movie is showing based on midTd data
getMovieShowingDates: function(movieId) {
const movieDates = new Set();
const movieIdWithPrefix = "fi" + movieId;
// Search through midTd to find all dates this movie plays
Object.keys(midTd).forEach(key => {
if (midTd[key].includes(movieIdWithPrefix)) {
const match = key.match(/d(\d+)/);
if (match && datesWeek.has(match[1])) {
movieDates.add(match[1]);
}
}
});
return Array.from(movieDates);
},
// Process movie IDs from DOM strings
processMovieIds: function(idArray) {
return idArray.map(id => id.replace('#efilm', ''));
},
// Load user preferences from cookies
loadUserPreferences: function() {
// Load sort preference
const sortPreference = getCookie('sortfilms');
if (sortPreference) {
this.sorting.currentSort = sortPreference;
}
// Load show only favorites setting
const showFavorites = getCookie('ccmovinfav');
this.data.showOnlyFavorites = (showFavorites === '1');
// Load genre filters
const filtg = getCookie('filtg').split(".");
filtg.forEach(genre => {
if (genre) this.filters.genres[genre] = true;
});
// Load language filters
const filtl = getCookie('filtl').split(".");
filtl.forEach(lang => {
if (lang) this.filters.languages[lang] = true;
});
// Load classification filters
const filtr = getCookie('filtr').split(".");
filtr.forEach(classification => {
if (classification) this.filters.classifications[classification] = true;
});
// Special features are not stored in cookies yet, we'll add that
},
// Save user preferences to cookies
saveUserPreferences: function() {
// Save genre filters
const genreFilters = Object.keys(this.filters.genres).filter(key => this.filters.genres[key]);
setCookie('filtg', genreFilters.join('.'), 1024);
// Save language filters
const langFilters = Object.keys(this.filters.languages).filter(key => this.filters.languages[key]);
setCookie('filtl', langFilters.join('.'), 1024);
// Save classification filters
const classFilters = Object.keys(this.filters.classifications).filter(key => this.filters.classifications[key]);
setCookie('filtr', classFilters.join('.'), 1024);
// Save sort preference
setCookie('sortfilms', this.sorting.currentSort, 1024);
// Save favorite cinema setting
setCookie('ccmovinfav', this.data.showOnlyFavorites ? '1' : '', this.data.showOnlyFavorites ? 1024 : 0);
// Save selected dates
sessionStorage.setItem('ccnpdates', JSON.stringify(this.data.selectedDates));
},
// Set up event listeners for all interactive elements
setupEventListeners: function() {
// We'll keep existing click handlers in the HTML, but update their functions
// This section is mostly informational since we don't modify the HTML
},
// Apply all current filters and update the display
applyFiltersAndUpdate: function() {
const visibleMovies = this.getVisibleMovies();
this.updateMovieVisibility(visibleMovies);
this.updateFilterUI();
this.saveUserPreferences();
this.updateMoviesHeader();
},
// Get movies that should be visible based on all current filters
getVisibleMovies: function() {
const result = {};
const allMovieIds = Object.keys(this.data.movies);
// Handle special feature filters first (they override other filters)
if (this.filters.special.parentsBabies) {
allMovieIds.forEach(id => {
if (this.data.movies[id].specialFeatures.parentsBabies) {
result[id] = true;
}
});
return result;
}
if (this.filters.special.sensoryFriendly) {
allMovieIds.forEach(id => {
if (this.data.movies[id].specialFeatures.sensoryFriendly) {
result[id] = true;
}
});
return result;
}
// Apply cinema filters first
allMovieIds.forEach(id => {
// Check if movie is showing in selected cinemas on selected dates
let movieShowsInSelectedCinema = false;
// See if this movie has any showtime in the selected cinema and dates
this.data.selectedDates.forEach(date => {
Object.keys(this.data.cinemas).forEach(cinemaId => {
const key = `t${cinemaId}d${date}`;
if (midTd[key] && midTd[key].includes(`fi${id}`)) {
movieShowsInSelectedCinema = true;
}
});
});
if (!movieShowsInSelectedCinema) return;
// Filter by favorites if enabled
if (this.data.showOnlyFavorites) {
const movieInFavorites = document.querySelector(`#efilm${id}`).classList.contains('infavcin');
if (!movieInFavorites) return;
}
// Apply genre filters if any
const activeGenreFilters = Object.keys(this.filters.genres).filter(g => this.filters.genres[g]);
if (activeGenreFilters.length > 0) {
const matchesGenre = activeGenreFilters.some(genre =>
this.data.movies[id].genres.includes(genre)
);
if (!matchesGenre) return;
}
// Apply language filters if any
const activeLangFilters = Object.keys(this.filters.languages).filter(l => this.filters.languages[l]);
if (activeLangFilters.length > 0) {
const matchesLanguage = activeLangFilters.some(lang =>
this.data.movies[id].languages.includes(lang)
);
if (!matchesLanguage) return;
}
// Apply classification filters if any
const activeClassFilters = Object.keys(this.filters.classifications).filter(c => this.filters.classifications[c]);
if (activeClassFilters.length > 0) {
const matchesClassification = activeClassFilters.some(classification =>
this.data.movies[id].classifications.includes(classification)
);
if (!matchesClassification) return;
}
// When the user has selected dates and the withCaptions filter
if (this.filters.special.withCaptions) {
const selectedCinemas = Object.keys(this.data.cinemas);
const selectedDates = this.data.selectedDates;
// Get movies with captions on selected dates in selected cinemas
const captionedMovies = getMoviesWithFeatureOnDates(
'withCaptions',
selectedDates,
selectedCinemas
);
// Update UI to show these movies and their caption dates
Object.keys(captionedMovies).forEach(movieElementId => {
// Use the full element ID to find the movie element
const movieElement = document.getElementById(movieElementId);
if (movieElement) {
// Format dates for display
const formattedDates = captionedMovies[movieElementId].dates.map(date => {
return formatDate(date); // Your date formatting function
}).join(', ');
// Add caption note
let noteElement = movieElement.querySelector('.special-feature-note');
if (!noteElement) {
noteElement = document.createElement('div');
noteElement.className = 'special-feature-note';
movieElement.appendChild(noteElement);
}
noteElement.textContent = `Captioned showings: ${formattedDates}`;
}
});
}
// Handle audio description filter
if (this.filters.special.withAudioDescription && !this.data.movies[id].specialFeatures.withAudioDescription) {
return;
}
// If we reach here, the movie passed all filters
result[id] = true;
});
return result;
},
// Update movie elements visibility based on filter results
updateMovieVisibility: function(visibleMovies) {
// First, remove all filter-related classes
document.querySelectorAll('.movieblock').forEach(movie => {
movie.classList.remove('thisFilmPlays', 'thisFilmNotPlays');
movie.classList.remove('filteredgenre', 'filteredlang', 'filteredclass', 'filterednonfavcin', 'filteredOne');
movie.classList.remove('tofiltergenre', 'tofilterlang', 'tofilterclass');
});
// Apply visibility classes
Object.keys(this.data.movies).forEach(id => {
const movieEl = document.getElementById(`efilm${id}`);
if (visibleMovies[id]) {
movieEl.classList.add('thisFilmPlays');
} else {
movieEl.classList.add('thisFilmNotPlays');
}
});
// Sort the visible movies
this.sortMovies();
// Show or hide special showtimes blocks
if (this.filters.special.parentsBabies) {
document.querySelectorAll("div.showtimeblock").forEach(el => el.style.display = "none");
document.querySelectorAll("div.showtimeblock.bab").forEach(el => el.style.display = "block");
} else if (this.filters.special.sensoryFriendly) {
document.querySelectorAll("div.showtimeblock").forEach(el => el.style.display = "none");
document.querySelectorAll("div.showtimeblock.sen").forEach(el => el.style.display = "block");
} else {
document.querySelectorAll("div.showtimeblock.bab, div.showtimeblock.sen").forEach(el => el.style.display = "none");
}
},
// Update UI elements related to filtering
updateFilterUI: function() {
// Count active filters
let filterCount = 0;
// Count genre filters
const activeGenres = Object.keys(this.filters.genres).filter(g => this.filters.genres[g]);
filterCount += activeGenres.length;
// Count language filters
const activeLangs = Object.keys(this.filters.languages).filter(l => this.filters.languages[l]);
filterCount += activeLangs.length;
// Count classification filters
const activeClasses = Object.keys(this.filters.classifications).filter(c => this.filters.classifications[c]);
filterCount += activeClasses.length;
// Count special filters
if (this.filters.special.parentsBabies) filterCount++;
if (this.filters.special.sensoryFriendly) filterCount++;
if (this.filters.special.withCaptions) filterCount++;
if (this.filters.special.withAudioDescription) filterCount++;
// Update filter note visibility
if (filterCount > 1) {
document.getElementById("firstfilter").style.display = "none";
document.getElementById("clearfilters").style.display = "inline";
} else if (filterCount > 0) {
document.getElementById("firstfilter").style.display = "inline";
document.getElementById("clearfilters").style.display = "none";
} else {
document.getElementById("firstfilter").style.display = "none";
document.getElementById("clearfilters").style.display = "none";
}
// Handle special filter notes
const specialFilterActive = this.filters.special.parentsBabies || this.filters.special.sensoryFriendly;
if (specialFilterActive && filterCount > 0) {
const noteEl = document.getElementById('activefiltersonenote');
noteEl.style.display = 'block';
if (this.filters.special.parentsBabies) {
const message = filterCount > 1
? 'Note: The
Parents & babies filter makes all other filters inactive.'
: 'Note: The
Parents & babies filter makes the other filter inactive.';
noteEl.innerHTML = message;
} else if (this.filters.special.sensoryFriendly) {
const message = filterCount > 1
? 'Note: The
Sensory-friendly filter makes all other filters inactive.'
: 'Note: The
Sensory-friendly filter makes the other filter inactive.';
noteEl.innerHTML = message;
}
} else {
document.getElementById('activefiltersonenote').style.display = 'none';
}
// Update available filter options based on currently visible movies
this.updateAvailableFilters();
},
// Update which filter options should be available based on current selection
updateAvailableFilters: function() {
const visibleMovies = this.getVisibleMovies();
// Update available genres
genresavailable.forEach(genre => {
const hasMoviesWithGenre = Object.keys(visibleMovies).some(id =>
this.data.movies[id].genres.includes(genre)
);
const genreEl = document.getElementById(`filgen${genre}`);
if (genreEl) {
if (hasMoviesWithGenre) {
genreEl.classList.remove("inactive");
} else {
genreEl.classList.add("inactive");
}
}
});
// Update available languages
languageclassesavailable.forEach(lang => {
const hasMoviesWithLang = Object.keys(visibleMovies).some(id =>
this.data.movies[id].languages.includes(lang)
);
const langEl = document.getElementById(`fil${lang}`);
if (langEl) {
if (hasMoviesWithLang) {
langEl.classList.remove("inactive");
} else {
langEl.classList.add("inactive");
}
}
});
// Update available ratings
const ratings = ['g', 'pg', '13', 'pg13', '14a', '16', '18', '18a', 'r', 'nc17'];
ratings.forEach(rating => {
const hasMoviesWithRating = Object.keys(visibleMovies).some(id => {
const ratingClass = `r${filtrat}${rating}`;
return this.data.movies[id].classifications.includes(ratingClass);
});
const ratingEl = document.getElementById(`filr${rating}`);
if (ratingEl) {
if (hasMoviesWithRating) {
ratingEl.classList.remove("inactive");
} else {
ratingEl.classList.add("inactive");
}
}
});
},
// Sort the movies list according to current sort preference
sortMovies: function() {
const sortOrder = this.sorting.sortMaps[this.sorting.currentSort];
const movieContainer = document.getElementById('allmovies');
const movieBank = document.getElementById('moviebank');
// If we have other hidden movies, move them to bank
if (othermovieshide && othermovieshide.length) {
othermovieshide.forEach(selector => {
const elements = document.querySelectorAll(selector);
elements.forEach(el => {
movieBank.appendChild(el);
});
});
}
// Empty the container
while (movieContainer.firstChild) {
movieContainer.removeChild(movieContainer.firstChild);
}
// Add movies in correct order
sortOrder.forEach(id => {
const movieElement = document.getElementById(`efilm${id}`);
if (movieElement) {
movieContainer.appendChild(movieElement);
}
});
// Show the container
movieContainer.style.display = 'block';
// Handle scroll position
const scrollPos = sessionStorage.getItem("nowplayingscroll");
if (scrollPos) {
const scrollValue = parseInt(scrollPos);
if (scrollValue < document.documentElement.scrollHeight) {
window.scrollTo(0, scrollValue);
}
}
// Save scroll position when scrolling
window.onscroll = function() {
sessionStorage.setItem("nowplayingscroll", window.pageYOffset);
};
},
// Update the dates selection based on user interaction
updateDates: function(date, clickedElement) {
if (clickedElement.classList.contains("disabled")) {
return;
}
const allActive = this.allDatesActive();
if (allActive) {
// If all are active, clicking one should deactivate all others
this.data.selectedDates = this.data.dates.filter(d => d === date);
this.data.dates.forEach(d => {
const element = document.getElementById(`datesel${d}`);
if (element && d !== date && !element.classList.contains("disabled")) {
element.classList.remove("active");
}
});
} else {
// Toggle the clicked date
if (this.data.selectedDates.includes(date)) {
// Remove date
this.data.selectedDates = this.data.selectedDates.filter(d => d !== date);
clickedElement.classList.remove("active");
} else {
// Add date
this.data.selectedDates.push(date);
clickedElement.classList.add("active");
}
// If no dates selected, select all
if (this.data.selectedDates.length === 0) {
this.data.selectedDates = [...this.data.dates];
this.data.dates.forEach(d => {
const element = document.getElementById(`datesel${d}`);
if (element) {
element.classList.add("active");
}
});
}
}
// Update date note
this.updateDateNote();
// Apply filters and update display
this.applyFiltersAndUpdate();
},
// Update the date note (showing that future dates may have incomplete listings)
updateDateNote: function() {
const anyFirstThreeActive = ['0401', '0402', '0403'].some(date =>
this.data.selectedDates.includes(date)
);
const noteEl = document.getElementById('showingOnlyDateNote');
if (anyFirstThreeActive) {
noteEl.innerHTML = ' ';
noteEl.classList.add('hidden');
} else {
noteEl.innerHTML = 'Movie list for future dates is incomplete; cinemas may add more films later.';
noteEl.classList.remove('hidden');
}
},
// Check if all non-disabled date buttons are active
allDatesActive: function() {
return this.data.dates.every(date => {
const element = document.getElementById(`datesel${date}`);
return !element || element.classList.contains("disabled") || element.classList.contains("active");
});
},
// Toggle a single genre filter
toggleGenreFilter: function(genreCode, genreText) {
const isActive = this.filters.genres[genreCode] === true;
if (isActive) {
// Remove the filter
delete this.filters.genres[genreCode];
// Remove from the active filters UI
const activeFilterEl = document.querySelector(`.activefiltergen${genreCode}`);
if (activeFilterEl) activeFilterEl.remove();
// Update the filter UI
const filterItem = document.getElementById(`filgen${genreCode}`);
if (filterItem) {
filterItem.classList.remove('filteractive');
const checkmark = filterItem.querySelector('.glyp.check');
if (checkmark) checkmark.classList.remove('checked');
}
} else {
// Add the filter
this.filters.genres[genreCode] = true;
// Add to the active filters UI
const filterVars = `'${genreCode}','${genreText}'`;
const activeFiltersContainer = document.getElementById('activefiltersgenre');
if (activeFiltersContainer) {
const filterButton = document.createElement('a');
filterButton.className = `buttonfilter activefiltergen${genreCode}`;
filterButton.setAttribute('onclick', `filterOneGenre(${filterVars})`);
filterButton.innerHTML = `Genre: ${genreText}
`;
activeFiltersContainer.appendChild(filterButton);
}
// Update the filter UI
const filterItem = document.getElementById(`filgen${genreCode}`);
if (filterItem) {
filterItem.classList.add('filteractive');
const checkmark = filterItem.querySelector('.glyp.check');
if (checkmark) checkmark.classList.add('checked');
}
}
// Close the filter dropdown with a delay
document.getElementById('filtergenrelist').addEventListener('mouseleave', function() {
document.getElementById('filtergenrelist').style.display = 'none';
document.getElementById('filtergenrelist').removeEventListener('mouseleave', arguments.callee);
});
this.applyFiltersAndUpdate();
},
// Toggle a single language filter
toggleLanguageFilter: function(langCode, langText) {
const isActive = this.filters.languages[langCode] === true;
if (isActive) {
// Remove the filter
delete this.filters.languages[langCode];
// Remove from the active filters UI
const activeFilterEl = document.querySelector(`.activefilterlan${langCode}`);
if (activeFilterEl) activeFilterEl.remove();
// Update the filter UI
const filterItem = document.getElementById(`fil${langCode}`);
if (filterItem) {
filterItem.classList.remove('filteractive');
const checkmark = filterItem.querySelector('.glyp.check');
if (checkmark) checkmark.classList.remove('checked');
}
} else {
// Add the filter
this.filters.languages[langCode] = true;
// Add to the active filters UI
const filterVars = `'${langCode}','${langText}'`;
const activeFiltersContainer = document.getElementById('activefilterslang');
if (activeFiltersContainer) {
const filterButton = document.createElement('a');
filterButton.className = `buttonfilter activefilterlan${langCode}`;
filterButton.setAttribute('onclick', `filtLang(${filterVars})`);
filterButton.innerHTML = `Language: ${langText}
`;
activeFiltersContainer.appendChild(filterButton);
}
// Update the filter UI
const filterItem = document.getElementById(`fil${langCode}`);
if (filterItem) {
filterItem.classList.add('filteractive');
const checkmark = filterItem.querySelector('.glyp.check');
if (checkmark) checkmark.classList.add('checked');
}
}
// Close the filter dropdown with a delay
document.getElementById('filterlanglist').addEventListener('mouseleave', function() {
document.getElementById('filterlanglist').style.display = 'none';
document.getElementById('filterlanglist').removeEventListener('mouseleave', arguments.callee);
});
this.applyFiltersAndUpdate();
},
// Toggle a single classification filter
toggleClassificationFilter: function(regClass, classCode, classText) {
const fullCode = `r${regClass}${classCode}`;
const isActive = this.filters.classifications[fullCode] === true;
if (isActive) {
// Remove the filter
delete this.filters.classifications[fullCode];
// Remove from the active filters UI
const activeFilterEl = document.querySelector(`.activefilterclass${classCode}`);
if (activeFilterEl) activeFilterEl.remove();
// Update the filter UI
const filterItem = document.getElementById(`filr${classCode}`);
if (filterItem) {
filterItem.classList.remove('filteractive');
const checkmark = filterItem.querySelector('.glyp.check');
if (checkmark) checkmark.classList.remove('checked');
}
} else {
// Add the filter
this.filters.classifications[fullCode] = true;
// Add to the active filters UI
const filterVars = `'${regClass}','${classCode}','${classText}'`;
const activeFiltersContainer = document.getElementById('activefiltersclass');
if (activeFiltersContainer) {
const filterButton = document.createElement('a');
filterButton.className = `buttonfilter activefilterclass${classCode}`;
filterButton.setAttribute('onclick', `filterOneClass(${filterVars})`);
filterButton.innerHTML = `Rating: ${classText}
`;
activeFiltersContainer.appendChild(filterButton);
}
// Update the filter UI
const filterItem = document.getElementById(`filr${classCode}`);
if (filterItem) {
filterItem.classList.add('filteractive');
const checkmark = filterItem.querySelector('.glyp.check');
if (checkmark) checkmark.classList.add('checked');
}
}
// Close the filter dropdown with a delay
document.getElementById('filterothlist').addEventListener('mouseleave', function() {
document.getElementById('filterothlist').style.display = 'none';
document.getElementById('filterothlist').removeEventListener('mouseleave', arguments.callee);
});
this.applyFiltersAndUpdate();
},
// Toggle a special feature filter
toggleSpecialFilter: function(code, text) {
let key;
// Map code to feature key
switch(code) {
case 'b': key = 'parentsBabies'; break;
case 's': key = 'sensoryFriendly'; break;
case 'c': key = 'withCaptions'; break;
case 'a': key = 'withAudioDescription'; break;
default: return;
}
const isActive = this.filters.special[key];
// Toggle the filter
this.filters.special[key] = !isActive;
// Update UI
const filterItem = document.getElementById(`filoth${code}`);
if (filterItem) {
if (this.filters.special[key]) {
filterItem.classList.add('filteractive');
const checkmark = filterItem.querySelector('.glyp.check');
if (checkmark) checkmark.classList.add('checked');
// Add to active filters
const filterVars = `'${code}','${text}'`;
const activeFiltersContainer = document.getElementById('activefiltersone');
const filterButton = document.createElement('a');
filterButton.className = `buttonfilter activefilteroth${code}`;
filterButton.setAttribute('onclick', `filterOneOnly(${filterVars})`);
filterButton.innerHTML = `${text}
`;
activeFiltersContainer.appendChild(filterButton);
} else {
filterItem.classList.remove('filteractive');
const checkmark = filterItem.querySelector('.glyp.check');
if (checkmark) checkmark.classList.remove('checked');
// Remove from active filters
const activeFilterEl = document.querySelector(`.activefilteroth${code}`);
if (activeFilterEl) activeFilterEl.style.display = 'none';
}
}
// Close the filter dropdown
document.getElementById('filterothlist').style.display = 'none';
this.applyFiltersAndUpdate();
},
// Toggle between showing all cinemas or only favorites
toggleFavorites: function(showOnlyFav) {
this.data.showOnlyFavorites = (showOnlyFav === '1');
// Update UI
if (showOnlyFav === '1') {
document.querySelector('a.incinall').classList.remove('buttopinv');
document.querySelector('a.incinfav').classList.add('buttopinv');
// Mark movies showing in favorite cinemas
const umall = getCookie('um');
const movieIds = umall.split('.');
movieIds.forEach(id => {
// Clean the ID (remove non-digits)
const cleanId = id.replace(/\D/g,'');
if (cleanId > 0) {
const selector = `div.fi${cleanId}`;
document.querySelectorAll(selector).forEach(el => {
el.classList.add('infavcin');
});
}
});
// Mark babies/sensory shows in favorite cinemas
const ucall = getCookie('uc');
const cinemaIds = ucall.split('.');
cinemaIds.forEach(id => {
if (id > 0) {
// Mark parent & babies screenings
const babSelector = `.babinkino${id}`;
document.querySelectorAll(babSelector).forEach(el => {
el.classList.add('infavcinbab');
});
// Mark sensory friendly screenings
const senSelector = `.seninkino${id}`;
document.querySelectorAll(senSelector).forEach(el => {
el.classList.add('infavcinsen');
});
}
});
// Save the preference
setCookie('ccmovinfav','1',1024);
} else {
// Update UI for showing all cinemas
document.querySelector('a.incinfav').classList.remove('buttopinv');
document.querySelector('a.incinall').classList.add('buttopinv');
document.querySelectorAll('div.movieblock').forEach(el => {
el.classList.remove('infavcin');
});
document.getElementById('showingOnlyOneGenreNoteNM').style.display = 'none';
// Remove the cookie
setCookie('ccmovinfav','',0);
}
// Apply filters and update display
this.applyFiltersAndUpdate();
},
// Clear all filters
clearAllFilters: function() {
// Reset all filter buttons
document.querySelectorAll('a.btn.btnccinv.fouroptions.filter').forEach(el => {
el.classList.remove('active');
});
// Reset all filter states
this.filters.genres = {};
this.filters.languages = {};
this.filters.classifications = {};
this.filters.special = {
parentsBabies: false,
sensoryFriendly: false,
withCaptions: false,
withAudioDescription: false
};
// Reset filter UI
document.getElementById('activefilterslang').innerHTML = '';
document.getElementById('activefiltersclass').innerHTML = '';
document.getElementById('activefiltersgenre').innerHTML = '';
document.getElementById('activefiltersone').innerHTML = '';
document.getElementById('activefiltersother').innerHTML = '';
// Remove checked marks
document.querySelectorAll('.glyp.check.checked').forEach(el => {
el.classList.remove('checked');
});
// Remove filter active states
document.querySelectorAll('div.fltritm').forEach(el => {
el.classList.remove('filteractive');
});
// Apply updates
this.applyFiltersAndUpdate();
},
// Change the current sort order
changeSort: function(sortBy) {
if (this.sorting.currentSort !== sortBy) {
this.sorting.currentSort = sortBy;
this.saveUserPreferences();
this.applyFiltersAndUpdate();
}
// Update UI for sort buttons
document.querySelectorAll('a.headoptions.sort').forEach(el => {
el.classList.remove('buttopinv');
});
let selector;
if (sortBy === 'value') {
selector = '#headswitchersortv';
} else if (sortBy === 'date') {
selector = '#headswitchersortd';
} else {
selector = '#headswitchersorta';
}
document.querySelector(selector).classList.add('buttopinv');
document.getElementById('filtergenrelist').style.display = 'none';
},
// Update the header with movie count
updateMoviesHeader: function() {
// Count visible movies
const visibleCount = document.querySelectorAll('.movieblock.thisFilmPlays').length;
// Update the counter in the header
const moviesCountEl = document.getElementById('moviescount');
if (moviesCountEl) {
moviesCountEl.textContent = `${visibleCount} Movie${visibleCount !== 1 ? 's' : ''} Playing`;
}
}
};
// Export these global functions that will be used by the existing event handlers
// These act as bridges between the existing HTML event handlers and our new code
/**
* Toggle a date's selection state
* @param {string} date - Date string in MMDD format
* @param {HTMLElement} clickedElement - The DOM element that was clicked
*/
function toggleDateFromUniqueDates(date, clickedElement) {
MovieListManager.updateDates(date, clickedElement);
}
/**
* Sort the movies by the specified criteria
* @param {string} sortBy - Sort criteria ('alpha', 'value', or 'date')
*/
function sortmoviesby(sortBy) {
MovieListManager.changeSort(sortBy);
}
/**
* Update the option bar UI when a sorting option is clicked
* @param {HTMLElement} theElement - The clicked element
* @param {string} sortBy - Sort criteria
*/
function sortmoviesbyclick(theElement, sortBy) {
updateoptionbar(theElement);
sortmoviesby(sortBy);
}
/**
* Toggle showing only movies in favorite cinemas
* @param {string} onlyinfav - '1' to show only favorites, '0' to show all
*/
function showOnlyInFavourite(onlyinfav) {
MovieListManager.toggleFavorites(onlyinfav);
}
/**
* Filter movies by genre
* @param {string} oneGenre - Genre code
* @param {string} oneGenreText - Genre display text
*/
function filterOneGenre(oneGenre, oneGenreText) {
MovieListManager.toggleGenreFilter(oneGenre, oneGenreText);
}
/**
* Filter movies by language
* @param {string} oneLang - Language code
* @param {string} oneLangText - Language display text
*/
function filtLang(oneLang, oneLangText) {
MovieListManager.toggleLanguageFilter(oneLang, oneLangText);
}
/**
* Filter movies by classification/rating
* @param {string} regClass - Region classification
* @param {string} oneClass - Classification code
* @param {string} oneClassText - Classification display text
*/
function filterOneClass(regClass, oneClass, oneClassText) {
MovieListManager.toggleClassificationFilter(regClass, oneClass, oneClassText);
}
/**
* Filter movies by special features (parents & babies, sensory-friendly)
* @param {string} oneOth - Special feature code
* @param {string} oneOthText - Special feature display text
*/
function filterOneOnly(oneOth, oneOthText) {
MovieListManager.toggleSpecialFilter(oneOth, oneOthText);
}
/**
* Clear all active filters
*/
function clearAllFilters() {
MovieListManager.clearAllFilters();
}
/**
* Update the movie list after cinema radius selection
*/
function updateMovieList() {
// Re-load cinema IDs from localStorage
const ccradtids = localStorage.getItem('ccradtids');
const ccradtidsA = JSON.parse(ccradtids);
const utids = ccradtidsA.map(item => parseInt(item, 10));
// Update cinema IDs in our manager
MovieListManager.data.cinemas = {};
utids.forEach(id => {
MovieListManager.data.cinemas[id] = true;
});
// Apply filters and update
MovieListManager.applyFiltersAndUpdate();
}
// Initialize the movie list manager when the page loads
document.addEventListener('DOMContentLoaded', function() {
// Add the captions and audio description options to the filter menu
const filterOthList = document.getElementById('filterothlist');
if (filterOthList) {
// Add the captions option at the top of the list
const captionsOption = document.createElement('div');
captionsOption.id = 'filothc';
captionsOption.className = 'fltritm';
captionsOption.onclick = function() { filterOneOnly('c', 'With Captions'); };
captionsOption.innerHTML = '
With Captions';
filterOthList.insertBefore(captionsOption, filterOthList.firstChild);
// Add the audio description option at the top of the list
const audioDescOption = document.createElement('div');
audioDescOption.id = 'filotha';
audioDescOption.className = 'fltritm';
audioDescOption.onclick = function() { filterOneOnly('a', 'With Audio Description'); };
audioDescOption.innerHTML = '
With Audio Description';
filterOthList.insertBefore(audioDescOption, filterOthList.firstChild);
}
// Initialize the toggle switch for favorite cinemas
const toggleSwitch = document.getElementById('toggleSwitch');
if (toggleSwitch) {
toggleSwitch.addEventListener('click', function() {
// Check if user has favorite cinemas
const ufavC = getCookie('uc');
if (ufavC.length <= 1) {
return; // No favorite cinemas, do nothing
}
// Toggle state
const currentState = toggleSwitch.classList.contains('active');
toggleSwitch.classList.toggle('active');
// Update format labels
document.getElementById('format12').classList.toggle('active');
document.getElementById('format24').classList.toggle('active');
// Update cookie and apply filter
const newState = toggleSwitch.classList.contains('active') ? '1' : '0';
showOnlyInFavourite(newState);
});
}
// Initialize our movie list manager
MovieListManager.init();
});