Смайлики поддерживают текстовое поле или контент-контент div

Попытка реализовать компонент textarea с поддержкой смайликов при записи.

Я хочу иметь возможность резервировать исходный текст (только символы ascii), представляя результат фильтрации/сгенерированного html (с фильтром смайликов angular) на div.

Мое начальное решение -

<textarea ng-model="text" ng-change="..." ng-focus="..."></textarea>
<div ng-bind-html="text | myEmoticonsFilter"></div>

но у меня возникают проблемы с тем, чтобы использовать скрытую текстовую область. Кроме того, с этим я не смог бы выбрать текст для выбора мыши и удалить или скопировать/вставить безопасно.

Я также думал об использовании <div contenteditable="true">, но ng-focus и ng-change не обрабатывался.

Есть ли у кого-нибудь какие-либо рекомендации относительно продолжения этого?

Изменить 1: здесь jsfiddle с попыткой сделать то, что я делаю. До сих пор можно было заменить первое вхождение, но с тех пор поведение остается неустойчивым. Я использую директиву contenteditable для привязки двухсторонних данных и фильтрации шаблона смайликов.

Изменить 2: в отношении моего утверждения о том, что ng-focus и ng-change не будут обрабатываться, это не так - ng-focus работает изначально на <div contenteditable="true"> и ng-change будет работайте, пока директива объявляется с помощью ngModel и устанавливает соответствующие $modelValue и $viewValue (пример приведен в jsfiddle в Изменить 1).

Ответ 1

Единственный способ сделать это в последовательно кросс-браузерном режиме - использовать поле WYSIWYG, которое преобразует emoji в изображения.

Там плагин jQuery jquery-emojiarea, который делает то, что вам нужно, поэтому вам просто нужно создать директиву, которая обертывает этот плагин и вы отправились на гонки. Поскольку он вводится в скрытую текстовую область с синтаксисом emoji :smile: angular, не должно быть затруднений с привязкой.

Вот рабочая директива, которую я бросил вместе. http://jsfiddle.net/dboskovic/g8x8xs2t/

var app = angular.module('app', []);
app.controller('BaseController', function ($scope) {
    $scope.text = 'This is pretty awesome. :smile: :laughing:';
});
app.directive('emojiInput', function ($timeout) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function ($scope, $el, $attr, ngModel) {
            $.emojiarea.path = 'https://s3-us-west-1.amazonaws.com/dboskovic/jquery-emojiarea-master/packs/basic';
            $.emojiarea.icons = {
                ':smile:': 'smile.png',
                ':angry:': 'angry.png',
                ':flushed:': 'flushed.png',
                ':neckbeard:': 'neckbeard.png',
                 ':laughing:': 'laughing.png'
            };
            var options = $scope.$eval($attr.emojiInput);
            var $wysiwyg = $($el[0]).emojiarea(options);
            $wysiwyg.on('change', function () {
                ngModel.$setViewValue($wysiwyg.val());
                $scope.$apply();
            });
            ngModel.$formatters.push(function (data) {
                // emojiarea doesn't have a proper destroy :( so we have to remove and rebuild
                $wysiwyg.siblings('.emoji-wysiwyg-editor, .emoji-button').remove();
                $timeout(function () {
                    $wysiwyg.emojiarea(options);
                }, 0);
                return data;
            });
        }
    };
});

И использование:

<textarea ng-model="text" emoji-input="{buttonLabel:'Insert Emoji',wysiwyg:true}"></textarea>

Если вы хотите, чтобы редактируемое поле конвертировало текст типа :( по мере ввода, вам нужно разблокировать этот плагин jquery и немного изменить его, чтобы проанализировать ввод текста при изменении, а также в init. (например, пару строк кода)