jQuery-плагин для вставки спецсимволов и эмодзи в поля input и textarea.
Ядро (charPicker.core.js) не зависит от jQuery и загружается лениво — только при первом открытии диалога. Страница подключает только лёгкий адаптер (~3 КБ).
| Файл | Когда подключать | Размер |
|---|---|---|
jquery.charPicker.v3.js |
С загрузкой страницы | ~3 КБ |
charPicker.core.js |
Автоматически при первом open() | ~40 КБ |
charPicker.core.css |
Автоматически при первом open() | ~5 КБ |
charpicker-data.min.json |
По запросу через dataUrl |
~170 КБ |
<!-- Подключение -->
<script src="/js/jquery.loadBundle.js"></script>
<script src="/js/jquery.charPicker.v3.js"></script>
<!-- Инициализация -->
<script>
$('.my-field').charPicker({
dataUrl: '/js/charpicker-data.min.json'
});
</script>Пути к charPicker.core.js и charPicker.core.css вычисляются автоматически — они должны лежать в той же папке что и jquery.charPicker.v3.js.
$('#my-field').charPicker({ dataUrl: '/js/data.json' });Плагин оборачивает поле в <span class="jcp"> и добавляет кнопку-триггер справа.
$('#my-field').charPicker({ trigger: false, dataUrl: '/js/data.json' });
// Открытие с позиционированием у кнопки:
$('#my-btn').on('click', function() {
$('#my-field').charPicker('open', this);
});$('#my-field').charPicker({
trigger: $('#toolbar .emoji-btn'), // плагин вешает click сам
dataUrl: '/js/data.json'
});Попап позиционируется относительно переданной кнопки.
$('#my-field').charPicker({
trigger: function(open) {
// this = DOM-элемент поля
var $btn = $('<button>☺</button>');
$btn.on('click', function(e) { open(e.currentTarget); });
$(this).closest('.form').find('.toolbar').append($btn);
},
dataUrl: '/js/data.json'
});| Опция | Тип | По умолч. | Описание |
|---|---|---|---|
dataUrl |
string | null |
URL JSON-файла с данными. При ошибке — fallback на встроенные данные |
data |
Array | null |
Готовый массив групп. Приоритет выше dataUrl |
panels |
Array | null |
Фильтр групп по id: ['smileys', 'math']. null — все группы |
trigger |
см. выше | 'auto' |
Режим создания кнопки-триггера |
anchor |
Element | null |
Статический якорь позиционирования |
position |
string | 'auto' |
Вертикаль попапа: 'auto' | 'top' | 'bottom' |
align |
string | 'field' |
Горизонталь попапа: 'field' | 'anchor' | 'cursor' |
closeOnPick |
boolean | false |
Закрывать диалог после выбора символа |
recentMax |
number | 32 |
Макс. символов в разделе «Недавние» |
onOpen |
Function | null |
Вызывается при открытии. this = DOM-элемент поля |
onClose |
Function | null |
Вызывается при закрытии. this = DOM-элемент поля |
onSelect |
Function(char, name) | null |
Вызывается при выборе символа |
onDataError |
Function(Error) | null |
Вызывается при ошибке загрузки dataUrl |
coreJs |
string | авто | URL charPicker.core.js |
coreCss |
string | авто | URL charPicker.core.css |
debug |
boolean | false |
Подробный лог в консоль |
| Значение | Поведение |
|---|---|
'field' |
Левый край попапа совпадает с левым краем поля ввода |
'anchor' |
Левый край попапа совпадает с левым краем кнопки/якоря |
'cursor' |
Попап открывается у точки клика (для MouseEvent/TouchEvent) |
// Открыть диалог
$('#my-field').charPicker('open');
// Открыть с позиционированием у элемента
$('#my-field').charPicker('open', document.getElementById('my-btn'));
// Закрыть
$('#my-field').charPicker('close');
// Переключить (open/close)
$('#my-field').charPicker('toggle');
// Удалить плагин
$('#my-field').charPicker('destroy');var cp = new CharPicker(inputElement, {
dataUrl: '/js/data.json',
onSelect: function(char, name) { console.log(char, name); }
});
cp.open(anchorElement); // Element | jQuery | MouseEvent | TouchEvent | null
cp.close();
cp.toggle(anchor);
cp.destroy();{
"version": "2.1.0",
"groups": [
{
"id": "smileys",
"label": "Смайлы",
"labelEn": "Smileys",
"icon": "😀",
"subgroups": [
{
"label": "Счастье",
"labelEn": "Happy",
"chars": [
{ "c": "😀", "n": "улыбка grinning face" },
{ "c": "😂", "n": "слёзы радости tears of joy" }
]
}
]
},
{
"id": "math",
"label": "Математика",
"labelEn": "Math",
"icon": "∑",
"chars": [
{ "c": "±", "n": "плюс минус plus minus" }
]
}
]
}Группы могут иметь либо subgroups, либо прямой массив chars — не оба сразу.
Поиск работает по полю n (название символа). Поддерживается:
- Прямой поиск — по названию на любом языке:
"сердце","heart" - Поиск символом —
"♥"найдёт символ напрямую - Конвертация раскладки EN↔RU —
"cbvdjk"найдёт"символ"(ввели латиницей в русской раскладке) - Нормализация ё→е —
"ёлка"и"елка"дают одинаковый результат
| Клавиша | Действие |
|---|---|
Tab |
Перемещение по элементам диалога |
↓ в поле поиска |
Переход на первый символ в гриде |
← ↑ → ↓ в гриде |
Навигация по символам с учётом числа колонок |
↑ / ← с первого символа |
Возврат на поле поиска |
Enter / Space |
Выбор символа |
Escape |
Закрыть диалог |
Выбранные символы сохраняются в localStorage['jcp_recent']. История общая для всех экземпляров на странице (один origin). В приватном режиме или при ограничениях iframe работает только в памяти — без ошибок.
Ограничить размер истории:
$('#my-field').charPicker({ recentMax: 16 });| Класс | Описание |
|---|---|
.jcp |
Обёртка вокруг поля (только trigger:'auto') |
.jcp__trigger |
Кнопка открытия (только trigger:'auto') |
.jcp__trigger--active |
Попап открыт |
.jcp__trigger--loading |
Идёт загрузка ядра |
.jcp__popup |
Всплывающий диалог |
.jcp__popup--pos-bottom |
Попап открывается вниз |
.jcp__popup--pos-top |
Попап открывается вверх |
.jcp__popup--pos-right |
Попап сдвинут к правому краю |
.jcp__search-input |
Поле поиска |
.jcp__tabs |
Панель вкладок |
.jcp__tab |
Одна вкладка |
.jcp__tab--active |
Активная вкладка |
.jcp__body |
Прокручиваемая область с символами |
.jcp__char |
Один символ |
.jcp__char--sym |
Не-эмодзи символ (serif-шрифт) |
.jcp__tooltip |
Тултип с именем символа |
.jcp__tooltip--visible |
Тултип виден |
Переопределите до @import:
$cp-popup-width : 320px;
$cp-popup-max-height : 420px;
$cp-char-size : 34px;
$cp-trigger-size : 2.2em;
$cp-color-accent : #5b9bd5;
$cp-color-bg : #fff;
$cp-z-popup : 9999;
@import 'charPicker.core';- XSS исключён — символы вставляются через
document.createTextNode(),el.value— никакогоinnerHTMLс пользовательскими данными - Нет eval — нет
eval(),new Function()или динамической компиляции - Изоляция обработчиков —
destroy()снимает только свои обработчики событий - Встроенные данные в Base64 — символы вроде
',",«не конфликтуют с JS-строками
- jQuery ≥ 1.9
jquery.loadBundle.js— для ленивой загрузки (опционально, есть fallback через<script>)- ES5-совместимый браузер + Promise (IE11 с polyfill)
Если $.loadBundle недоступен, плагин использует встроенный fallback через динамические теги <link> и <script>:
// Всё работает без jquery.loadBundle.js,
// но ядро загрузится чуть позже из-за отсутствия prefetch CSS
$('.my-field').charPicker({ dataUrl: '/js/data.json' });При открытии через file:// XHR-запросы заблокированы браузером. Плагин автоматически переключается на встроенный набор данных (~645 символов, 5 групп). Для тестирования с полным набором откройте страницу через локальный веб-сервер (Live Server, python -m http.server, etc.).
charPicker.core.js— архитектурно отделён от jQuery: не создаёт кнопок и wrap'ов, управляет только попапомopen(anchor)— принимает Element, jQuery, MouseEvent, TouchEvent или plain-rectposition:fixedдля попапа — корректное позиционирование при прокрученной странице- Опция
align— горизонтальное выравнивание:field|anchor|cursor - Опция
closeOnPick— управление закрытием после выбора - Клавиатурная навигация по гриду символов (стрелки, Enter/Space)
- Автоопределение пути к файлам ядра по расположению плагина
- Fallback на встроенные данные при ошибке
dataUrl(в т.ч.file://) - Защита от ложного закрытия при скролле после вставки символа
- Тултип
display:noneкогда не виден — не перекрывает страницу - Опция
debug:true— подробный лог событий в консоль
- Разделение на
charPicker.core.js+jquery.charPicker.v3.js(Stub-паттерн) - Ленивая загрузка ядра при первом
open() - История «Недавних» сохраняется в
localStorage - Поиск с конвертацией раскладки EN↔RU и нормализацией ё→е
- Встроенные данные в Base64 (без AJAX)
- Drag-scroll вкладок