伙计们,你好吗?我在保存光标位置和插入动态标签时遇到麻烦。我使用Emojiarea插件创建了一个div,可以在其中编写文本,插入表情符号,模板和标签。 https://github.com/mervick/emojionearea
我使用以下功能在我的文本区域上创建一个div:
$("#email_campaign_description").emojioneArea({
search: false,
recentEmojis: false,
pickerPosition: "right",
events: {
blur: function (editor, event) {
$scope.lastPosition = getCaretCharacterOffsetWithin(editor[0])
},
}
});
当我单击时,下一个函数返回光标的最后位置 文本中的某处:
function getCaretCharacterOffsetWithin(element) {
var caretOffset = 0;
var doc = element.ownerDocument;
var win = doc.defaultView;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
debugger
return caretOffset;
}
最后一个函数将动态标签添加到文本:
$scope.chooseTag = function (label) {
var domElement = $('#email_campaign_description');
var emojiElement = domElement[0].emojioneArea;
if (document.selection) {
domElement.focus();
var sel = document.selection.createRange();
sel.text = $scope.tags.model;
domElement.focus();
} else if ($scope.lastPosition) {
var startPos = $scope.lastPosition;
var endPos = startPos + $scope.tags.model[0].length;
emojiElement.setText(emojiElement.getText().substring(0, startPos) + ' ' + $scope.tags.model + ' ' + emojiElement.getText().substring(endPos, emojiElement.getText().length));
domElement.focus();
} else {
emojiElement.setText($scope.tags.model);
domElement.focus();
}
if ($scope.tags.model === '[vendor_name]') {
emojiElement.setText(domElement.val().replace('[vendor_name]', $scope.vendor.name));
}
$scope.campaign.description = $('#email_campaign_description').val();
};
会发生问题,即在文本中存储点击位置的函数无法读取表情符号。因此,如果我写这样的文字:“你好,[表情符号],欢迎光临!”在该文本的结尾,我尝试添加标签,我的函数将不会读取表情符号,而是将标签插入句子的最后一个字符(本例中为“!”)。同样,如果我添加两个表情符号,则在这种情况下,“ o!”将不会读取并在最后两个字符上插入标签。正确的方法是读取这两个表情符号并将我的标签准确地添加到所需位置的功能,即:“你好[表情符号],欢迎使用[标签]”
function getCaretCharacterOffsetWithin(element)
可以读取表情符号作为字符或占用的空间怎么办?
答案 0 :(得分:1)
问题在于javascript不能很好地处理Unicode字符串。
例如:
"hello".length === 5
"???".length === 7
有几个库可以帮助准确测量unicode字符串的长度。 Graphemer是其中之一(完整披露:我已发布此库)。
要修复您的getCaretCharacterOffsetWithin(element)
函数,请执行以下操作:
import Graphemer from 'graphemer';
const splitter = new Graphemer();
function getCaretCharacterOffsetWithin(element) {...}
caretOffset = preCaretRange.toString().length; // original
caretOffset = splitter.countGraphemes(preCaretRange.toString()); // updated
caretOffset = preCaretTextRange.text.length; // original
caretOffset = splitter.countGraphemes(preCaretTextRange.text); // updated