Pull to refresh

Эмоции.js

Reading time2 min
Views23K


В статье описывается опыт создания текстового поля с возможностью вставки смайлов, проблемы которые мне встретились и их решения, а так же ссылка на репозиторий с готовым jQuery плагином. Если вам интересно, прошу под кат.

Во время разработки моего первого проекта мне поставили задачу, создать чат со смайлами. Основной функционал чата был готов, но приступив к смайлам у меня возникла проблема, я не мог вставить смайл в текущую позицию курсора, получалось только в начало или конец текстового поля. Опыта у меня было ноль, как в программировании так и в поиске нужной информации, поэтому не смог найти ничего «работоспособного» и тем более готовых решений. Помучавшись две-три недели я сдался и пришлось сказать ненавистные мне слова «Я не могу это реализовать».

Прошло уже около трех лет и недавно у моего коллеги встала та же задача, он спросил меня, как это можно сделать. Воспоминания о неудаче вдруг хлынули волной и мне захотелось решить мою давнюю неосуществимую задачу.

Поиски готового решения снова закончились безрезультатно, но с документацией было уже намного лучше, узнав о document.getSelection() тут же кинулся писать код и конечно же встретил еще несколько проблем и как всегда на одну из них ушло больше всего времени.

Нашел примерно такое решение
if (window.getSelection) {
    var sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
        var range = window.getSelection().getRangeAt(0);
        range.insertNode(document.createTextNode(text));
    }
}

Что было очевидно, при клике на смайл фокус переходил к нему и нужный нам контент вставлялся в него, а не в наше текстовое поле. Решение было простым, запретить фокусироваться на блоке с эмоциями.
$emojiContainer.attr({
  unselectable: 'on',
       onselectstart: 'return false;',
       onmousedown: 'return false;'
});


Вторая проблема оказалась для меня посложнее, смайл вставлялся после курсора, но сам курсор не двигался вперед в связи с чем каждая последующая эмоция была впереди предыдущей.

После прочтения замечательной статьи от bur все немного прояснилось.
Написал функцию которая вставляет курсор после элемента, решение оказалось простым.

function SetCursorAfterElement(element)
{
    var selection = window.getSelection();
    selection.removeAllRanges();
    var range = document.createRange();
    range.setStartAfter(element);
    selection.addRange(range);
}


На данный момент это jQuery плагин и поддерживается браузерами IE9+. В ближайших планах переписать код без использованием jQuery и с поддержкой старых браузеров, да и код написан не продумано, без особой гибкости. Буду рад если кому то сэкономил время.

KEmoji.js
Демо

Update
Код переписан на нативный js, скрипт оптимизирован, смайлы перемещены в одну картинку + добавлен генератор карты смайлов (на php), который из папки со смайлами делает одну картинку с css файлом
Tags:
Hubs:
+11
Comments35

Articles

Change theme settings