[СДЕЛАЙ САМ] Поиск с mSearch2 и SendIt без перезагрузки страницы и динамическими параметрами
Приветствую, думаю ни для кого не секрет, что mSearch2 не умеет показывать результаты поиска без перезагрузки страницы, а pdoPage не умеет «на лету» менять параметры. На своём сайте я захотел сделать морфологический поиск услуг без перезагрузки, с постраничной навигацией и возможностью выбирать категорию поиска. Ниже опишу чтобы для этого было предпринято.
1. Разметка
Для начала нам нужна форма для ввода запроса и выбора категории, блок для вставки результатов и блок для вставки пагинации. Выглядит это примерно так:
2. Сниппет-обработчик
Для обработки формы на сервере нужен сниппет:
После того как наш сниппет запустил mSearch2 и pdoPage нам нужно вывести результаты, для этого понадобится примерно такой JS
Этот код добавит запрос и родителя в get-параметры, что позволит делится ссылкой (@Дима Касаткин спасибо за идею), если в вызове pdoPage вы эти параметры укажете примерно вот так
4. Обработка переключения страницы
При переключении страницы нужно дополнительно отправлять на сервер выбранные параметры (запрос и родителя). Дл этого нужно изменить оригинальный JS pdoPage (assets/components/pdotools/js/pdopage.js). В методе pdoPage.loadPage в конце блока объявления переменных (после стр. 128) нужно добавить наши данные
На этом изменения в оригинальном JavaScript закончены. Отмечу, что править исходный файл не нужно, сделайте копию и измените системную настройку с путями к скриптам фронтенда.
5. Собственный коннектор
Поскольку на предыдущем шаге мы добавили в запрос новые параметры, нужно научить коннектор их обрабатывать. ДЛя этого я сделал копию родного коннектора и внёс изменения после 24 строки
В данный момент ведётся активная работа над MiniShop3 силами сообщества и руками @Николай Савин, поэтому призываю всех неравнодушных поддержать эту работу финансово.
1. Разметка
Для начала нам нужна форма для ввода запроса и выбора категории, блок для вставки результатов и блок для вставки пагинации. Выглядит это примерно так:
<form id="searchForm" data-si-form="searchForm" data-si-preset="search">
<label>
<input type="text" name="query" placeholder="Ключевые слова">
</label>
<div>
<select name="parent">
<option value="36">Выберите категорию</option>
<!-- вызов спиппета pdoResources -->
</select>
</div>
<button type="submit">Найти</button>
</form>
<div id="results">
<!-- вызов спиппета pdoPage -->
</div>
<div id="pagination">
<!-- пагинация -->
</div>
У меня за отправку формы отвечает сниппет SendIt, вы можете использовать тот, который вам больше нравится.2. Сниппет-обработчик
Для обработки формы на сервере нужен сниппет:
<?php
$_GET['query'] = $_POST['query'];
/*
тут должен быть массив параметров вызова pdoPage
я их получаю из файла с пресетами,
но это актуально только при использовании MigxPageConfigurator
*/
$params = include(MODX_BASE_PATH . $presetPath);
$catalogParams = $params[$presetName];
foreach ($catalogParams as $k => $v) {
$catalogParams[$k] = str_replace('#/', '@FILE chunks/', $v);
}
/*
устанавливаем параметры вызова из запроса
*/
$catalogParams['parents'] = (int)$_POST['parent'];
if ($_POST['query'] && strlen($_POST['query']) >= $catalogParams['minQuery']) {
$catalogParams['resources'] = $modx->runSnippet('mSearch2', ['parents' => (int)$_POST['parent'], 'limit' => 0, 'returnIds' => 1]);
}
/*
проверяем поменялся ли родитель с прошлого запроса
если поменялся значит это новая выборка и нужно перейти на первую страницу
*/
if ($_SESSION['liveSearch']['parent'] !== (int)$_POST['parent'] || $_SESSION['liveSearch']['query'] !== $_POST['query']) {
$_GET['page'] = 1;
}
/*
устанавливаем отступ
*/
if ((int)$_POST['current_page'] && (int)$_POST['current_page'] <= (int)$_POST['total_pages']) {
$params['offset'] = ((int)$_POST['current_page'] - 1) * $catalogParams['limit'];
}
/*
получаем плейсхолдеры сгенерированные pdoPage
*/
$html = $modx->runSnippet('pdoPage', $catalogParams);
$page = (int)$modx->getPlaceholder($catalogParams['pageVarKey'] ?: 'page');
$pagination = $modx->getPlaceholder($catalogParams['pageNavVar'] ?: 'page.nav');
/*
записываем параметры запроса в сессию
*/
$_SESSION['liveSearch']['resources'] = $catalogParams['resources'];
$_SESSION['liveSearch']['parent'] = $_POST['parent'];
$_SESSION['liveSearch']['query'] = $_POST['query'];
return $SendIt->success('', ['html' => $html, 'parent' => (int)$_POST['parent'], 'page' => $page, 'query' => $_POST['query'], 'pagination' => $pagination]);
3. Обработка ответа сервераПосле того как наш сниппет запустил mSearch2 и pdoPage нам нужно вывести результаты, для этого понадобится примерно такой JS
document.addEventListener('si:send:finish', async (e) => {
const results = document.querySelector('#results');
const pagination = document.querySelector('#pagination');
const url = window.location.href;
const params = new URLSearchParams(window.location.search);
e.detail.result.data.parent ? params.set('parent', e.detail.result.data.parent) : params.delete('parent');
e.detail.result.data.query ? params.set('query', e.detail.result.data.query) : params.delete('query');
if(e.detail.result.data.page ><code></code> 1){
params.set('page', e.detail.result.data.page);
}else{
params.delete('page');
pdoPage.keys[pdoPage.configs.page['pageVarKey']] = 1;
}
if(params.toString()){
window.history.replaceState({}, '', url.split('?')[0] + '?' + params.toString());
}else{
window.history.replaceState({}, '', url.split('?')[0]);
}
if(results){
results.innerHTML = e.detail.result.data.html;
}
if(pagination){
pagination.innerHTML = e.detail.result.data.pagination;
}
});
Этот код добавит запрос и родителя в get-параметры, что позволит делится ссылкой (@Дима Касаткин спасибо за идею), если в вызове pdoPage вы эти параметры укажете примерно вот так
{'!pdoPage' | snippet: [
'element' => 'msProducts',
'resources' => ('!mSearch2' | snippet: ['parents' => $.get.parent, 'limit' => 0, 'returnIds' => 1])?: '999999'
...
]}
Я привел примерный код, поскольку в моём вариант после загрузки происходит автоматическая отправка формы, при наличии сохранённых параметров.4. Обработка переключения страницы
При переключении страницы нужно дополнительно отправлять на сервер выбранные параметры (запрос и родителя). Дл этого нужно изменить оригинальный JS pdoPage (assets/components/pdotools/js/pdopage.js). В методе pdoPage.loadPage в конце блока объявления переменных (после стр. 128) нужно добавить наши данные
var query = wrapper.find('[name="query"]');
var parent = wrapper.find('[name="parent"]');
А после блока формирования параметров нужно добавить наши данные к нимif(query.length){
params['query'] = query.val();
}
if(parent.length){
params['parent'] = parent.val();
}
На строке 173 замените config['connectorUrl'] на путь к вашему коннектору (зачем он нужен читайте ниже).На этом изменения в оригинальном JavaScript закончены. Отмечу, что править исходный файл не нужно, сделайте копию и измените системную настройку с путями к скриптам фронтенда.
5. Собственный коннектор
Поскольку на предыдущем шаге мы добавили в запрос новые параметры, нужно научить коннектор их обрабатывать. ДЛя этого я сделал копию родного коннектора и внёс изменения после 24 строки
/*
если уже есть найденные ресурсы
значит нужно перейти на другую страницу
в другом случае надо перейти на первую страницу
*/
if ($_SESSION['liveSearch']['resources']) {
$scriptProperties['resources'] = $_SESSION['liveSearch']['resources'];
} else {
if ($_SESSION['liveSearch']['parent'] !== $_GET['parent'] || $_SESSION['liveSearch']['query'] !== $_GET['query']) {
$_GET['page'] = 1;
}
$scriptProperties['parents'] = $_SESSION['liveSearch']['parent'];
}
Вот и всё. Посмотреть как это работает можно тут.В данный момент ведётся активная работа над MiniShop3 силами сообщества и руками @Николай Савин, поэтому призываю всех неравнодушных поддержать эту работу финансово.
- ВКонтакте
- Telegram
- Viber
- РЎРєРѕРїРСвЂВВВВВВВВровать ссылку
3
996
+13
Поблагодарить автора
Отправить деньги
Здесь упомянуты:
Компонент | Текущая версия | Закачки |
mSearch2 | 1.14.12-pl от 09.01.2025 | 19 273 |
SendIt | 2.3.0-pl от 04.04.2025 | 782 |
pdoTools | 2.13.2-pl от 02.09.2021 | 54 258 |
MigxPageConfigurator | 1.1.5-pl от 05.02.2024 | 17 |
miniShop2 | 4.4.0-pl от 06.08.2024 | 26 389 |
8 часов назад
Здравствуйте
Есть желание использовать компонент polylang для автоматизации перевода с наименьшими усилиями, но есть пару вопросов, которые хотелось ...
Polylang 143
Вчера в 16:30
Добрый день.
Удалите плагин vpSystem от пакета.
[VirtualPage] - Виртуальные страницы. 183
Вчера в 08:40
Хочестя в тикеты при сохранении комментария добавить кнопку «проверить на ошибки» и при нажатии на нее проверить комментарий на ошибки в нейросети сох...
pbStudio: Создаём сайт с PageBlocks – настройка и главная страница 6
Вчера в 08:36
Нет, через апи идет запрос в ChatGPT, который формирует необходимые данные о блоке, а дальше PageBlocks их разбирает и создает все нужные элементы.
PageBlocks 2.6.0. Настройка меню MODX и гибкое управление страницей пользователя 12
Вчера в 00:03
Не работает парсинг с vk.com, vkvideo.ru
[videoGallery] 1.4.0 Поддержка VK Video и ещё пара фишек 9
17 апреля 2025, 23:01
Можете тоже подсказать как победить данную ошибку?
msGallerySearch - загрузка изображений в галерею minishop2 по ссылке и Google поиск картинок 44
17 апреля 2025, 21:35
Действительно! Самого главного я и не обозначил! Спасибо! Поправлю заголовок.
Речь идет именно о панели менеджера и возможности управления заказами.
...
Вывод перечня заказанных товаров в таблицу с заказами minishop2 (панель менеджера) 8
17 апреля 2025, 17:49
Очевидно ты используешь источник файлов, поэтому в админке путь прописан от источника, хочешь полный путь, откажись от источника файлов.
Не открываются загруженные файлы пишет страница не найдена 2
17 апреля 2025, 15:08
Привет, Henk. Спасибо за ответ! В посте по ссылке меня больше всего заинтересовала фраза «мы интегрировали AI в медиа-менеджер, чтобы значительно упро...
MODX/AI Hackathon Part 2 (27 марта) 4
17 апреля 2025, 13:17
в preg_match проверка проходит, и туда 100% приходит url
Здравствуйте! Первый раз такое вижу, у слеша, не 1 символ в строке, а 9!! Как это делает MODX 2