添加emoji表情到编辑框,并且在任意光标后

依赖于emoji 库,主要是雪碧图实现表情的统一。
采用div标签的contenteditable属性实现编辑功能。 难点在于选择表情时的光标位置保存。实现任意光标位置插入表情。
实现一个小小的demo供大家参考, 共同学习!
添加emoji表情到编辑框,并且在任意光标后_第1张图片
部分代码仅供参考,共同学习

难点部分;
1、选择表情时的光标位置保存
// 保存上次光标位置信息
var lastEditRange;
var editEle = document.getElementById('edit');
// 编辑框点击事件
editEle.onclick = function() {
    // 获取选定对象
    var selection = getSelection();
    // 设置最后光标对象
    lastEditRange = selection.getRangeAt(0);
};

// 编辑框按键弹起事件
editEle.onkeyup = function() {
    // 获取选定对象
    var selection = getSelection();
    // 设置最后光标对象
    lastEditRange = selection.getRangeAt(0);
};
2、在任意位置插入表情
function _insertimg(str) {
    var selection = window.getSelection
        ? window.getSelection()
        : document.selection;
    document.getElementById(elName).focus();
    if (lastEditRange) {
        // 存在最后光标对象,选定对象清除所有光标并添加最后光标还原之前的状态
        selection.removeAllRanges();
        selection.addRange(lastEditRange);
    }
    var range = selection.createRange
        ? selection.createRange()
        : selection.getRangeAt(0);
    if (!window.getSelection) {
        var selection = window.getSelection
            ? window.getSelection()
            : document.selection;
        var range = selection.createRange
            ? selection.createRange()
            : selection.getRangeAt(0);
        range.pasteHTML(str);
        range.collapse(false);
        range.select();
    } else {
        var hasR = range.createContextualFragment(str);
        var hasR_lastChild = hasR.lastChild;
        while (
            hasR_lastChild &&
            hasR_lastChild.nodeName.toLowerCase() == 'br' &&
            hasR_lastChild.previousSibling &&
            hasR_lastChild.previousSibling.nodeName.toLowerCase() == 'br'
        ) {
            var e = hasR_lastChild;
            hasR_lastChild = hasR_lastChild.previousSibling;
            hasR.removeChild(e);
        }
        range.insertNode(hasR);
        if (hasR_lastChild) {
            range.setEndAfter(hasR_lastChild);
            range.setStartAfter(hasR_lastChild);
        }
        range.collapse(false);
        selection.removeAllRanges();
        selection.addRange(range);
    }
    // 无论如何都要记录最后光标对象
    lastEditRange = selection.getRangeAt(0);
}
3、表情字符转义
function emojiToUnicode(emoji) {
    var backStr = '';
    if (emoji && emoji.length > 0) {
        for (var char of emoji) {
            var index = char.codePointAt(0);
            if (index > 65535) {
                var h =
                    '\\u' +
                    (Math.floor((index - 0x10000) / 0x400) + 0xd800).toString(
                        16
                    );
                var c =
                    '\\u' + ((index - 0x10000) % 0x400 + 0xdc00).toString(16);
                backStr = backStr + h + c;
            } else {
                backStr = backStr + char;
            }
        }
        console.log(backStr);
    }
    return backStr;
}

function utf16toEntities(str) {
    //检测utf16emoji表情 转换为实体字符以供后台存储
    var patt = /[\ud800-\udbff][\udc00-\udfff]/g;
    str = str.replace(patt, function(char) {
        var H, L, code;
        if (char.length === 2) {
            //辅助平面字符(我们需要做处理的一类)
            H = char.charCodeAt(0); // 取出高位
            L = char.charCodeAt(1); // 取出低位
            code = (H - 0xd800) * 0x400 + 0x10000 + L - 0xdc00; // 转换算法
            return '&#' + code + ';';
        } else {
            return char;
        }
    });
    return str;
}

console.log('ssss---->', emojiToUnicode('��adfa我们'));
// console.log('utf16toEntities222222--->', utf16toEntities('\ud83d\ude00adfa我们'))
$('.box').append(utf16toEntities('\ud83d\ude00adfa我们'));
emoji库 GitHub地址 emoji库地址
完整代码地址 完整代码下载

你可能感兴趣的:(javascript)