Почему не работает мультивыбор для вложенных чекбоксов?
Всем салют! Контекст: создать каталог университетов на Wordpress.
Имеется:
Структура Базы Данных в phpMyAdmin:
TABLE wp_5pk4xpx5av_universities ( id INT PRIMARY KEY, name VARCHAR(255), about TEXT, slug VARCHAR(255) ); TABLE wp_5pk4xpx5av_address ( id INT PRIMARY KEY, country VARCHAR(255), city VARCHAR(255) );
Вложенные чекбоксы, которые работают по принципу: если выбран родительский чекбокс "Страна", то активны все вложенные чекбоксы"Город"; если выбран хотя бы один вложенный чекбокс "Город", то активен родительский чекбокс "Страна".
Что я сделал: разметку страницы каталога и код для вывода и фильтрации результатов:
<?php
global $wpdb;
// Получение уникальных стран из таблицы адресов
$query_countries = "SELECT DISTINCT country FROM {$wpdb->prefix}address";
$countries = $wpdb->get_col($query_countries);
?>
<form method="GET">
<?php foreach ($countries as $country) : ?>
<!-- Основной чекбокс для выбора страны -->
<input type="checkbox" name="country" value="<?php echo esc_attr($country); ?>" <?php echo (isset($_GET['country']) && $_GET['country'] == $country) ? 'checked' : ''; ?> class="country-checkbox">
<?php echo esc_html($country); ?><br>
<?php
// Получение уникальных городов для выбранной страны
$query_cities = $wpdb->prepare("SELECT DISTINCT city FROM {$wpdb->prefix}address WHERE country = %s", $country);
$cities = $wpdb->get_col($query_cities);
?>
<!-- Вложенные чекбоксы для выбора города -->
<div style="height: 100px; overflow-y: auto; margin-left: 10px;">
<?php foreach ($cities as $city) : ?>
<input type="checkbox" name="city" value="<?php echo esc_attr($city); ?>" <?php echo (isset($_GET['city']) && $_GET['city'] == $city) ? 'checked' : ''; ?> class="city-checkbox" data-country="<?php echo esc_attr($country); ?>">
<?php echo esc_html($city); ?><br>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
<br>
<!-- Кнопка для применения фильтра -->
<input type="submit" value="Применить фильтр">
</form>
<script>
document.addEventListener('DOMContentLoaded', function () {
var countryCheckboxes = document.querySelectorAll('.country-checkbox');
var cityCheckboxes = document.querySelectorAll('.city-checkbox');
// Обработчик события для чекбоксов стран
countryCheckboxes.forEach(function (countryCheckbox) {
countryCheckbox.addEventListener('change', function () {
var country = this.value;
var cityCheckboxesForCountry = document.querySelectorAll('.city-checkbox[data-country="' + country + '"]');
// Проверка активации/деактивации чекбоксов городов
cityCheckboxesForCountry.forEach(function (cityCheckbox) {
cityCheckbox.checked = countryCheckbox.checked;
});
});
});
// Обработчик события для чекбоксов городов
cityCheckboxes.forEach(function (cityCheckbox) {
cityCheckbox.addEventListener('change', function () {
var country = this.dataset.country;
var countryCheckbox = document.querySelector('.country-checkbox[value="' + country + '"]');
// Проверка активации/деактивации родительского чекбокса страны
checkParentCountryCheckbox(countryCheckbox);
});
});
// Функция для проверки и установки состояния родительского чекбокса страны
function checkParentCountryCheckbox(countryCheckbox) {
var country = countryCheckbox.value;
var cityCheckboxesForCountry = document.querySelectorAll('.city-checkbox[data-country="' + country + '"]');
var anyCityCheckboxSelected = false;
// Проверка, выбран ли хотя бы один чекбокс города
cityCheckboxesForCountry.forEach(function (cityCheckbox) {
if (cityCheckbox.checked) {
anyCityCheckboxSelected = true;
}
});
// Установка состояния родительского чекбокса страны
countryCheckbox.checked = anyCityCheckboxSelected;
});
// Добавляем обработчик для формы
var filterForm = document.querySelector('form');
filterForm.addEventListener('submit', function (event) {
// Предотвращаем отправку формы, чтобы обработать ее через AJAX
event.preventDefault();
// Ваш код обработки фильтрации, например, использование AJAX
// ...
// В этом примере, вы можете использовать функцию filterResults, которую вы определите
filterResults();
});
// Функция для фильтрации результатов
function filterResults() {
// Ваш код для фильтрации результатов
// ...
// Вывод результатов или отправка запроса на сервер
alert('Фильтр применен. Обработка результатов...');
}
});
</script>
Для вывода карточек университетов имеется следующий код:
<?php
global $wpdb;
// Получение данных из таблицы universities и address с объединением по id и фильтрацией
// Фильтрация по стране и городу, если установлены параметры фильтрации
$country_filter = isset($_GET['country']) ? sanitize_text_field($_GET['country']) : '';
$city_filter = isset($_GET['city']) ? sanitize_text_field($_GET['city']) : '';
$where_clause = '';
if ($country_filter || $city_filter) {
$where_clause = 'WHERE ';
if ($country_filter) {
$where_clause .= "a.country = '$country_filter'";
}
if ($city_filter) {
if ($country_filter) {
$where_clause .= ' AND ';
}
$where_clause .= "a.city = '$city_filter'";
}
}
$table_universities = $wpdb->prefix . 'universities';
$table_address = $wpdb->prefix . 'address';
$query = "SELECT u.id, u.name, u.about, a.country, a.city, u.slug
FROM $table_universities u
LEFT JOIN $table_address a ON u.id = a.id
$where_clause";
$universities_data = $wpdb->get_results($query);
// Вывод данных
if ($universities_data) {
foreach ($universities_data as $university_data) {
$university_url = esc_url(get_permalink(get_page_by_path('university')) . '?slug=' . $university_data->slug);
?>
<!-- link university card -->
<a href="<?php echo $university_url; ?>" id="w-node-_9317e69e-04a2-aa70-fb98-6f892678c56b-d20c27ce" class="card-container bg-color-white">
<h2 class="text-size-medium">
<?php echo esc_html($university_data->name); ?>
</h2>
<div class="text-size-regular">
<?php echo esc_html($university_data->about); ?>
</div>
<div class="w-layout-vflex tags">
<div class="w-layout-vflex tag">
<div class="text-size-regular">
<?php echo esc_html($university_data->country); ?>
</div>
</div>
<div class="w-layout-vflex tag">
<div class="text-size-regular">
<?php echo esc_html($university_data->city); ?>
</div>
</div>
</div>
</a>
<?php
}
} else {
echo 'No universities found.';
}
?>
<!-- end university card -->
Что я ожидал: допустим, у вас есть университеты в странах "USA", "UK" и "Canada". При выборе нескольких городов в фильтре, ожидается, что карточки университетов будут отображаться только для выбранных городов в пределах выбранной страны и в адресе страницы отображение соответствующих условий (example.com/?country=USA&city=Pittsfield&city=Lancaster)
Для страны USA имеются чекбоксы:
- USA (родительский)
-- Pittsfield (дочерний)
-- Lancaster (дочерний)
-- ... (дочерний)
При выборе города
-- Pittsfield (дочерний)
-- Lancaster (дочерний)
Фильтруется и остаётся активным значение для всех выбранных городов "-- Pittsfield" и "-- Lancaster" и в результатах появляется карточка универа для "-- Pittsfield" и "-- Lancaster" .
Что я получил: при выборе двух городов в фильтре для одной страны, после клика на кнопку "Применить" и перезагрузки страницы, я получаю результаты только по последнему чекбоксу в списке вложенных чекбоксов и соответствующую карточку университета из города, который является последним чекбоксом в списке вложенных чекбоксов, а так же в адресе страницы отображение соответствующих условий (example.com/?country=USA&city=Pittsfield&city=Lancaster). Если наглядно, то:
Для страны USA имеются чекбоксы:
- USA (родительский)
-- Pittsfield (дочерний)
-- Lancaster (дочерний)
-- ...
При выборе городов
-- Pittsfield (дочерний)
-- Lancaster (дочерний)
Фильтруется и остаётся активным значение для всех выбранных городов "-- Lancaster" и в результатах появляется карточка универа для города, в котором указано значение "-- Lancaster" .
Вопрос: что добавить/изменить в коде для фильтров, чтобы работал мультивыбор для вложенных чекбоксов? Ведь в адресе страницы существует отображение соответствующих условий (example.com/?country=USA&city=Pittsfield&city=Lancaster), но фильтрованные карточки университетов говорят об обратном. Рабочий аналогичный пример здесь.