Tooltips (всплывающие подсказки) в MikoPBX используются для предоставления контекстной помощи пользователям при работе с расширенными настройками. Система построена на базе Fomantic-UI (Semantic-UI) popup компонента и обеспечивает единообразный пользовательский опыт во всех разделах административного интерфейса.
- HTML-разметка: Иконки с классом
field-info-iconи атрибутомdata-field - JavaScript-инициализация: ВСЕГДА через
TooltipBuilder.initialize(htmlConfigs, options)— см.sites/admin-cabinet/assets/js/src/main/TooltipBuilder.js - Генератор контента:
TooltipBuilder.buildContent(config)(либо обёрткаform.buildTooltipContent()страницы, которая делегирует вTooltipBuilder) - Переводы: Локализованные тексты в файлах переводов (
src/Common/Messages/*.php) - Глобальная защита от toggle-чекбоксов:
TooltipBuilder.jsв DOMReady навешивает делегированныйclick.global-tooltipна.field-info-icon, .special-checkbox-info, .service-info-icon, который останавливает propagation/preventDefault, если иконка вложена в<label>. Дублировать это per-page НЕ нужно.
- Не вызывайте
$icon.popup({...})напрямую для.field-info-icon. Голыйpopup()безon: 'manual'и безlastResort: true:- hover не срабатывает стабильно, когда иконка вложена в
<label>тогл-чекбокса (Semantic UI checkbox перехватывает указатель на всём label), - Fomantic скрывает тултип целиком, если ни одна позиция не помещается во вьюпорт (тогда как
lastResort: trueфорсирует размещение и включает скролл внутри.field-info-popup).
- hover не срабатывает стабильно, когда иконка вложена в
- Не дублируйте per-page handler
click.tooltip-prevent— глобальный делегат вTooltipBuilder.jsуже это закрывает; per-iconclick.popup-triggerставит самTooltipBuilder.initialize().
{
header: 'Заголовок подсказки', // Основной заголовок
description: 'Описание функции', // Общее описание
list: [ // Основной список
// Простые элементы списка
'Элемент списка 1',
'Элемент списка 2',
// Элементы с определениями
{ term: 'Термин', definition: 'Определение' },
// Заголовки секций (definition: null)
{ term: 'Заголовок секции', definition: null }
],
list2: [...], // Дополнительные списки (list2-list10)
warning: { // Предупреждение
header: 'Внимание',
text: 'Текст предупреждения'
},
examples: [ // Примеры кода/конфигурации
'[section]',
'parameter = value',
'another_param = value'
],
examplesHeader: 'Примеры', // Заголовок для примеров
note: 'Дополнительное примечание' // Финальное примечание
}<!-- Базовая иконка tooltip -->
<label>{{ t._('ex_FieldLabel') }}
<i class="small info circle icon field-info-icon"
data-field="field_name"></i>
</label>
<!-- Tooltip для checkbox -->
<div class="ui toggle checkbox">
{{ form.render('field_name') }}
<label for="field_name">{{ t._('ex_CheckboxLabel') }}
<i class="small info circle icon field-info-icon"
data-field="field_name"></i>
</label>
</div>Эталон — GeneralSettings/general-settings-tooltip-manager.js (статический класс-менеджер на страницу) + main/TooltipBuilder.js (общая фабрика popup-ов).
/* global globalTranslate, TooltipBuilder */
class MyPageTooltipManager {
constructor() {
throw new Error('MyPageTooltipManager is static');
}
static getTooltipConfigurations() {
return {
field_name: {
header: globalTranslate.field_tooltip_header,
description: globalTranslate.field_tooltip_desc,
list: [
globalTranslate.field_tooltip_item1,
{ term: globalTranslate.field_tooltip_term,
definition: globalTranslate.field_tooltip_definition }
],
warning: {
header: globalTranslate.field_tooltip_warning_header,
text: globalTranslate.field_tooltip_warning
}
},
// ...
};
}
static initialize() {
if (typeof TooltipBuilder === 'undefined') {
console.error('TooltipBuilder is not available');
return;
}
// TooltipBuilder сам выполнит buildContent() для каждого конфига,
// навесит popup({on: 'manual', lastResort: true, ...}) и
// click.popup-trigger с stopPropagation/preventDefault.
TooltipBuilder.initialize(this.getTooltipConfigurations(), {
selector: '.field-info-icon',
position: 'top right',
hoverable: true,
showDelay: 300,
hideDelay: 100,
variation: 'flowing'
});
}
}Подключение в *-modify.js:
const myPage = {
initialize() {
// ... другая инициализация
if (typeof MyPageTooltipManager !== 'undefined') {
MyPageTooltipManager.initialize();
}
}
};
$(document).ready(() => myPage.initialize());
// НЕ добавляйте здесь свой $('.field-info-icon').on('click.tooltip-prevent', ...).
// Это уже сделано глобально в TooltipBuilder.js DOMReady.Когда иконка вложена в <label> для тогл-чекбокса/радио (Semantic UI .ui.toggle.checkbox), label-площадь перехватывает указатель — hover на <i> не срабатывает. on: 'manual' + click.popup-trigger явно показывает popup по клику на иконку и НЕ переключает чекбокс (благодаря stopPropagation()).
Длинные тултипы (несколько list1..list10) на типовых высотах вьюпорта (~720-800px) не помещаются ни в одну позицию из списка кандидатов. Без lastResort: true Fomantic скрывает popup целиком вместо того, чтобы разместить его по-умолчанию и включить скролл внутри .field-info-popup (CSS делает overflow-y: auto).
Если вы хотите хранить конфиги в формате уже-HTML (например, для динамических вставок типа firewall с iptables-командами), оборачивайте TooltipBuilder.buildContent() и передавайте в TooltipBuilder.initialize() уже строки HTML. TooltipBuilder.initialize() корректно отрабатывает оба варианта (объект-конфиг и готовая HTML-строка).
В файле переводов (src/Common/Messages/ru.php):
// Tooltips для поля field_name
'field_tooltip_header' => 'Заголовок подсказки',
'field_tooltip_desc' => 'Описание функциональности поля',
'field_tooltip_item1' => 'Элемент списка 1',
'field_tooltip_term' => 'Термин',
'field_tooltip_definition' => 'Определение термина',
'field_tooltip_warning_header' => 'Внимание',
'field_tooltip_warning' => 'Текст предупреждения о возможных последствиях',Tooltips для:
- Транспорт (sip_transport): Выбор протокола SIP с описанием каждого варианта
- Сетевой фильтр (sip_networkfilterid): Предупреждение о безопасности
- DTMF режим (sip_dtmfmode): Технические детали каждого режима
- Дополнительные атрибуты (sip_manualattributes): Примеры конфигурации
Базовый класс с универсальным методом buildTooltipContent() для:
- SIP провайдеров
- IAX провайдеров
- Общих настроек NAT и qualify
Специализированные tooltips:
- Динамическая генерация контента в зависимости от окружения
- Интеграция с ClipboardJS для копирования команд
- Показ iptables правил
- Сложные технические настройки: Параметры, требующие понимания протоколов
- Настройки безопасности: Предупреждения о последствиях изменений
- Редко используемые опции: Расширенные параметры конфигурации
- Форматы ввода: Примеры правильного заполнения полей
- Заголовок: Краткое название функции
- Описание: 1-2 предложения о назначении
- Детали: Списки опций или технические подробности
- Примеры: Конкретные примеры использования
- Предупреждения: Важная информация о безопасности или совместимости
- Используйте понятный язык, избегайте жаргона где возможно
- Предоставляйте конкретные примеры значений
- Группируйте связанную информацию в списки
- Выделяйте предупреждения оранжевым блоком
- Ограничивайте объем информации для удобства чтения
- Всегда используйте класс
field-info-iconдля иконок - Обязательно указывайте атрибут
data-fieldс именем поля - Инициализируйте tooltips после загрузки DOM
- ВСЕГДА используйте
TooltipBuilder.initialize()— никогда$icon.popup()напрямую - Параметр
hoverable: trueоставляйте включённым (это поведение popup-а, удерживающего его при наведении на сам popup) - Задавайте задержки показа/скрытия для улучшения UX
Модули могут добавлять свои tooltips:
- Создайте переводы в файле модуля
- Добавьте иконки в шаблоны представлений
- Инициализируйте tooltips в JavaScript модуля
- Используйте существующий метод
buildTooltipContent()
При добавлении новых tooltips:
- Следуйте установленной структуре данных
- Добавляйте переводы только на русский язык (остальные через Weblate)
- Тестируйте отображение на разных разрешениях экрана
- Проверяйте корректность позиционирования popup
- Убедитесь в отсутствии конфликтов с другими UI элементами
Система tooltips в MikoPBX обеспечивает единообразный способ предоставления контекстной помощи пользователям. Следование данным рекомендациям гарантирует консистентность пользовательского интерфейса и улучшает общий опыт работы с системой.