styles/prosilver/template создаём файл emoji_panel.js с таким текстом:
Код: Выделить всё
(function() {
// 1. АВТОНОМНОЕ ПОДКЛЮЧЕНИЕ IMGBB (если решите использовать комбо-вариант, иначе этот блок просто страхует)
if (!document.getElementById('imgbb-plugin-script') && document.querySelector('script[src*="://imgbb.com"]')) {
// Оставляем пустую проверку, чтобы не дублировать, если скрипт ImgBB уже есть в шаблоне
}
// 2. ЛОГИКА ПАНЕЛИ ЭМОДЗИ
const rawEmojis = '😀🤣😉🤫😳😘😋🧐😭🤬🤯🥵🥶🤮🥳❤️💃🍻💩👌👉👈👇☝️👍👎👏💪💯➕✔❌✅⭕';
const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
const emojis = Array.from(segmenter.segment(rawEmojis), segment => segment.segment);
let container = null;
let listContainer = null;
let currentTextarea = null;
function createContainer() {
if (container) return;
container = document.createElement('div');
container.id = 'phpbb-emoji-container';
// z-index выставлен с запасом, чтобы перекрывать другие элементы формы
container.style.cssText = 'display: none; position: absolute; z-index: 10000; background: #fff; border: 1px solid #ccc; padding: 6px; box-shadow: 0 -4px 8px rgba(0,0,0,0.1); border-radius: 4px; max-width: 452px;';
listContainer = document.createElement('div');
listContainer.id = 'phpbb-emoji-list';
listContainer.style.cssText = 'display: grid; grid-template-columns: repeat(20, 22px); font-size: 16px; text-align: center;';
container.appendChild(listContainer);
document.body.appendChild(container);
const fragment = document.createDocumentFragment();
emojis.forEach(function(emoji) {
const span = document.createElement('span');
span.textContent = emoji;
span.style.cssText = 'cursor:pointer;user-select:none;padding:0;transition:transform 0.1s;display:flex;align-items:center;justify-content:center;width:22px;height:22px;overflow:hidden;line-height:22px;box-sizing:border-box;';
span.onmouseenter = () => span.style.transform = 'scale(1.25)';
span.onmouseleave = () => span.style.transform = 'scale(1)';
span.addEventListener('click', function(e) {
e.preventDefault();
if (!currentTextarea) return;
const start = currentTextarea.selectionStart, end = currentTextarea.selectionEnd, scrollTop = currentTextarea.scrollTop;
currentTextarea.value = currentTextarea.value.substring(0, start) + emoji + currentTextarea.value.substring(end);
currentTextarea.focus();
currentTextarea.selectionStart = currentTextarea.selectionEnd = start + emoji.length;
currentTextarea.scrollTop = scrollTop;
});
fragment.appendChild(span);
});
listContainer.appendChild(fragment);
}
function injectEmojiButton(colorButton, textarea) {
if (!colorButton || !textarea || colorButton.nextElementSibling?.classList.contains('phpbb-emoji-trigger')) return;
const newButton = document.createElement('button');
newButton.type = 'button';
newButton.className = 'button button-icon-only responsive-hide phpbb-emoji-trigger';
newButton.title = 'Выбрать эмодзи';
newButton.innerHTML = '<i class="icon fa-smile-o fa-fw" aria-hidden="true"></i>';
newButton.style.marginLeft = '4px';
colorButton.parentNode.insertBefore(newButton, colorButton.nextSibling);
newButton.onclick = function(e) {
e.preventDefault();
e.stopPropagation();
// Если панель уже открыта именно для ЭТОЙ кнопки — закрываем её без лишних условий
if (container.style.display === 'block' && container.dataset.activeButton === newButton.title) {
container.style.display = 'none';
container.dataset.activeButton = "";
return;
}
currentTextarea = textarea;
container.dataset.activeButton = newButton.title; // Запоминаем текущий активный триггер
const rect = newButton.getBoundingClientRect();
// Фиксированная высота нашей панели (62px). Из top кнопки вычитаем 62px и 5px зазор.
container.style.top = (window.scrollY + rect.top - 67) + 'px';
container.style.left = (window.scrollX + rect.left) + 'px';
container.style.display = 'block';
};
}
function autoScanAndInject() {
const colorButtons = document.querySelectorAll('[name="bbpalette"], #bbpalette, .bbcode-color');
if (colorButtons.length > 0) {
createContainer();
colorButtons.forEach(colorBtn => {
const parentForm = colorBtn.closest('form') || colorBtn.closest('.quickreply') || colorBtn.closest('#qr_postform') || document;
const textarea = parentForm.querySelector('textarea');
if (textarea) {
injectEmojiButton(colorBtn, textarea);
}
});
}
}
setInterval(autoScanAndInject, 500);
document.addEventListener('click', function(e) {
if (container && container.style.display === 'block') {
if (!container.contains(e.target) && !e.target.closest('.phpbb-emoji-trigger')) {
container.style.display = 'none';
}
}
});
})();
overall_footer.html перед закрывающим тегом </body> дописываем строчку:
Код: Выделить всё
<!-- INCLUDEJS emoji_panel.js -->
