Skip to content

Commit df88f77

Browse files
authored
Merge pull request #878 from modx-pro/msearch
Обновлена документация msearcg
2 parents 4eb58ae + 1851628 commit df88f77

7 files changed

Lines changed: 369 additions & 17 deletions

File tree

docs/components/msearch/extending.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ $msearch = $modx->services->get('msearch');
422422
$results = $msearch->search('купить смартфон', [
423423
'limit' => 20,
424424
'offset' => 0,
425+
'contexts' => ['web'], // фильтрация по контекстам (опционально)
425426
]);
426427

427428
$results->getTotal(); // общее количество

docs/components/msearch/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ items: [
2323
{ text: 'Словари', link: 'interface/dictionaries' },
2424
],
2525
},
26+
{ text: 'JavaScript API', link: 'javascript-api' },
2627
{ text: 'Расширение компонента', link: 'extending' },
2728
]
2829
---
@@ -40,6 +41,10 @@ items: [
4041
- **Отложенная индексация** — фоновая индексация через [Scheduler](/components/scheduler/)
4142
- **Vue-интерфейс** — современная админ-панель на Vue 3 + PrimeVue
4243
- **Автодополнение** — подсказки при вводе запроса
44+
- **Публичный API** — REST endpoint для AJAX-поиска и интеграций
45+
- **Headless-режим** — JavaScript API (`window.msearch`) для React/Vue/кастомных решений
46+
- **Система хуков** — расширение поведения поиска через `msearchHooks`
47+
- **Мульти-контекст** — фильтрация результатов по контекстам MODX
4348

4449
## Системные требования
4550

@@ -128,6 +133,7 @@ mse_index_fields = pagetitle:3,longtitle:2,description:2,introtext:2,content:1
128133
|-----------|--------------|----------|
129134
| `mse_frontend_css` | `[[++assets_url]]components/msearch/css/web/msearch.css` | URL CSS файла |
130135
| `mse_frontend_js` | `[[++assets_url]]components/msearch/js/web/msearch.js` | URL JS файла |
136+
| `mse_cors_origin` | *(пусто)* | Разрешённый Origin для CORS на публичном API. Если пусто — разрешены only same-origin запросы |
131137

132138
## Плейсхолдеры
133139

docs/components/msearch/interface/aliases.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
|---------|----------|
4040
| Слово | Исходное слово (что ищет пользователь) |
4141
| Замена | Слово для замены/добавления |
42-
| Полная замена | `Replace` — замена, `Add` — синоним |
42+
| Полная замена | `Замена` — замена, `Добавление` — синоним |
4343
| Активен | Статус алиаса |
4444

4545
### Действия
@@ -58,7 +58,7 @@
5858
- **Замена** — на что заменить или что добавить
5959
- **Полная замена** — включить для режима замены
6060
- **Активен** — включить/отключить алиас
61-
3. Нажмите **Save**
61+
3. Нажмите **Сохранить**
6262

6363
## Примеры использования
6464

docs/components/msearch/interface/queries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
Анализируйте популярные запросы без результатов:
3939

40-
1. Найдите запросы с `Найдено: No`
40+
1. Найдите запросы с `Найдено: Нет`
4141
2. Определите, есть ли на сайте релевантный контент
4242
3. Если контент есть — проверьте индексацию
4343
4. Если контента нет — рассмотрите его создание
Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
# JavaScript API
2+
3+
mSearch предоставляет слоёную JavaScript-архитектуру для интеграции поиска на фронтенде. Можно использовать полный стек с UI, или только headless-режим для кастомных интерфейсов.
4+
5+
## Архитектура
6+
7+
```
8+
ApiClient — HTTP-клиент для API
9+
10+
SearchAPI — фасад поискового API
11+
12+
msearchHooks — система хуков
13+
14+
msearch — headless точка входа (window.msearch)
15+
16+
MSearchUI — UI-слой с автокомплитом (опционально)
17+
18+
msearch.js — автоинициализация (опционально)
19+
```
20+
21+
## Публичный API endpoint
22+
23+
Все JS-запросы идут на `assets/components/msearch/api.php`.
24+
25+
### Поиск
26+
27+
```
28+
GET /assets/components/msearch/api.php?route=/search&query=текст&limit=10&offset=0&ctx=web
29+
```
30+
31+
Ответ:
32+
33+
```json
34+
{
35+
"success": true,
36+
"total": 42,
37+
"limit": 10,
38+
"offset": 0,
39+
"query": "текст",
40+
"items": [
41+
{
42+
"id": 123,
43+
"pagetitle": "Заголовок",
44+
"longtitle": "Расширенный заголовок",
45+
"description": "Описание",
46+
"uri": "page/alias",
47+
"url": "https://site.com/page/alias",
48+
"intro": "Фрагмент с <mark>подсветкой</mark>",
49+
"weight": 45.0
50+
}
51+
]
52+
}
53+
```
54+
55+
### Автодополнение
56+
57+
```
58+
GET /assets/components/msearch/api.php?route=/search/suggest&query=те&limit=5&ctx=web
59+
```
60+
61+
Ответ:
62+
63+
```json
64+
{
65+
"success": true,
66+
"items": [
67+
{
68+
"id": 123,
69+
"pagetitle": "Заголовок",
70+
"url": "https://site.com/page/alias",
71+
"intro": "Фрагмент с <mark>подсветкой</mark>"
72+
}
73+
]
74+
}
75+
```
76+
77+
### Параметры
78+
79+
| Параметр | Тип | Описание |
80+
|----------|-----|----------|
81+
| `query` | string | Поисковый запрос |
82+
| `limit` | int | Количество результатов (по умолчанию 10 для search, 5 для suggest) |
83+
| `offset` | int | Смещение (только для search) |
84+
| `ctx` | string | Контексты через запятую (например `web` или `web,ru`) |
85+
86+
## Headless-режим
87+
88+
Headless-режим предоставляет программный API (`window.msearch`) без привязки к DOM. Подходит для React, Vue, Svelte и любых кастомных интерфейсов.
89+
90+
### Подключение
91+
92+
```html
93+
<script src="/assets/components/msearch/js/web/core/ApiClient.js"></script>
94+
<script src="/assets/components/msearch/js/web/core/SearchAPI.js"></script>
95+
<script src="/assets/components/msearch/js/web/modules/hooks.js"></script>
96+
<script src="/assets/components/msearch/js/web/msearch.headless.js"></script>
97+
```
98+
99+
### Конфигурация
100+
101+
```html
102+
<script>
103+
window.msearchConfig = {
104+
apiUrl: '/assets/components/msearch/api.php',
105+
ctx: 'web',
106+
autoInit: true
107+
};
108+
</script>
109+
```
110+
111+
При `autoInit: true` (по умолчанию) объект `window.msearch` инициализируется автоматически после загрузки DOM.
112+
113+
### Использование
114+
115+
```js
116+
// Поиск
117+
const result = await msearch.search('смартфон', { limit: 5 });
118+
console.log(result.total); // 42
119+
console.log(result.items); // [{id, pagetitle, url, intro, weight}, ...]
120+
121+
// Автодополнение
122+
const suggestions = await msearch.suggest('см', { limit: 3 });
123+
console.log(suggestions.items); // [{id, pagetitle, url, intro}, ...]
124+
```
125+
126+
### Ручная инициализация
127+
128+
```js
129+
await msearch.init({
130+
apiUrl: '/assets/components/msearch/api.php',
131+
ctx: 'web'
132+
});
133+
```
134+
135+
### События
136+
137+
| Событие | Описание |
138+
|---------|----------|
139+
| `msearch:ready` | Headless API инициализирован |
140+
| `msearch:ui:ready` | UI-слой инициализирован (если подключён) |
141+
142+
```js
143+
document.addEventListener('msearch:ready', (e) => {
144+
const msearch = e.detail.msearch;
145+
// API готов к использованию
146+
});
147+
```
148+
149+
## Система хуков
150+
151+
Хуки позволяют расширять поведение поиска: модифицировать запросы, обрабатывать результаты, логировать.
152+
153+
### Доступные хуки
154+
155+
| Хук | Описание |
156+
|-----|----------|
157+
| `beforeSearch` | Перед отправкой поискового запроса |
158+
| `afterSearch` | После получения результатов поиска |
159+
| `beforeSuggest` | Перед запросом автодополнения |
160+
| `afterSuggest` | После получения подсказок |
161+
| `onError` | При ошибке любого запроса |
162+
163+
### Подписка
164+
165+
```js
166+
// Добавить хук (возвращает функцию отписки)
167+
const unsubscribe = msearchHooks.add('beforeSearch', function(context) {
168+
console.log('Ищем:', context.query);
169+
// Можно модифицировать:
170+
// context.query — поисковый запрос
171+
// context.options — параметры запроса
172+
// context.cancelled = true — отменить запрос
173+
});
174+
175+
// Отписаться
176+
unsubscribe();
177+
```
178+
179+
### Приоритеты
180+
181+
```js
182+
// Хук с более низким числом выполняется раньше
183+
msearchHooks.add('afterSearch', analyticsHook, 5); // первый
184+
msearchHooks.add('afterSearch', transformHook, 10); // второй
185+
msearchHooks.add('afterSearch', renderHook, 20); // третий
186+
```
187+
188+
### Примеры
189+
190+
#### Логирование поисковых запросов
191+
192+
```js
193+
msearchHooks.add('afterSearch', function(context) {
194+
if (context.result && context.result.total > 0) {
195+
console.log(`Найдено ${context.result.total} по запросу "${context.query}"`);
196+
}
197+
});
198+
```
199+
200+
#### Модификация запроса
201+
202+
```js
203+
msearchHooks.add('beforeSearch', function(context) {
204+
// Добавить фильтр по контексту
205+
context.options.ctx = 'web';
206+
});
207+
```
208+
209+
#### Отмена запроса
210+
211+
```js
212+
msearchHooks.add('beforeSearch', function(context) {
213+
if (context.query.length < 3) {
214+
context.cancelled = true;
215+
context.result = { success: true, items: [], total: 0 };
216+
}
217+
});
218+
```
219+
220+
#### Обработка ошибок
221+
222+
```js
223+
msearchHooks.add('onError', function(context) {
224+
showNotification('Ошибка поиска: ' + context.error.message);
225+
});
226+
```
227+
228+
## UI-слой
229+
230+
UI-слой добавляет автокомплит к формам с атрибутом `data-msearch-form`. Подключается автоматически через сниппет mSearchForm при `autocomplete=1`.
231+
232+
### Ручное создание
233+
234+
```js
235+
const instance = MSearchUI.create(document.querySelector('#my-form'), {
236+
minQueryLength: 2,
237+
debounceDelay: 300,
238+
ctx: 'web'
239+
});
240+
```
241+
242+
### Data-атрибуты
243+
244+
Форма может передавать настройки через data-атрибуты:
245+
246+
| Атрибут | Описание |
247+
|---------|----------|
248+
| `data-msearch-form` | Маркер для автоинициализации |
249+
| `data-ctx` | Контекст для фильтрации |
250+
| `data-connector-url` | URL API endpoint |
251+
| `data-autocomplete` | `true` / `false` |
252+
| `data-min-query-length` | Минимальная длина запроса (по умолчанию 2) |
253+
| `data-debounce-delay` | Задержка debounce в мс (по умолчанию 300) |
254+
255+
### CSS-классы
256+
257+
| Класс | Элемент |
258+
|-------|---------|
259+
| `.mse-form` | Форма поиска |
260+
| `.mse-input` | Поле ввода |
261+
| `.mse-button` | Кнопка отправки |
262+
| `.mse-autocomplete` | Dropdown-список подсказок |
263+
| `.mse-autocomplete.active` | Открытый dropdown |
264+
| `.mse-autocomplete-item` | Элемент подсказки |
265+
| `.mse-autocomplete-item.active` | Выделенный элемент (стрелками) |
266+
267+
### Управление экземплярами
268+
269+
```js
270+
// Получить экземпляр по ID формы
271+
const instance = MSearchUI.get('my-form-id');
272+
273+
// Уничтожить экземпляр
274+
MSearchUI.destroy('my-form-id');
275+
```
276+
277+
## Пример: Vue 3 интеграция
278+
279+
```html
280+
<script src="/assets/components/msearch/js/web/core/ApiClient.js"></script>
281+
<script src="/assets/components/msearch/js/web/core/SearchAPI.js"></script>
282+
<script src="/assets/components/msearch/js/web/modules/hooks.js"></script>
283+
<script src="/assets/components/msearch/js/web/msearch.headless.js"></script>
284+
```
285+
286+
```js
287+
// В Vue-компоненте
288+
import { ref, onMounted } from 'vue';
289+
290+
export default {
291+
setup() {
292+
const query = ref('');
293+
const results = ref([]);
294+
const total = ref(0);
295+
296+
onMounted(() => {
297+
// msearch уже инициализирован через msearchConfig
298+
});
299+
300+
async function search() {
301+
if (query.value.length < 2) return;
302+
const data = await window.msearch.search(query.value, { limit: 10 });
303+
results.value = data.items;
304+
total.value = data.total;
305+
}
306+
307+
return { query, results, total, search };
308+
}
309+
};
310+
```
311+
312+
## CORS
313+
314+
Публичный API (`api.php`) по умолчанию разрешает только same-origin запросы. Для кросс-доменных запросов укажите разрешённый Origin в системной настройке `mse_cors_origin`.

0 commit comments

Comments
 (0)