我在StackOverflow上看到了一些有关此的问题,但是似乎很难找到基于jQuery的解决方案。因此,我想问这个问题。
我想用属性div
即时替换contenteditable="true"
内的文本。
我正在寻找一个基于jQuery的解决方案,该解决方案将执行以下操作:
我看过SC编辑器(http://www.sceditor.com/),似乎确实做到了这一点(例如,如果您尝试键入:)
,它将被表情符号代替。
我认为一个好的开始是将所有元素替换为一个数组:
$.settings = {
path: 'https://example.com/images/',
emoticons: {
':(' : 'stupid.jpg',
':)' : 'smart.jpg',
}
}
我一直找不到很好的例子。如果有人可以分享他们的想法和与此相关的任何代码,将非常高兴。
如何使用上述代码以最佳的方式完成替换?
我发现了这个。如果进行调整,它可能会满足您的需求。它将{替换为{},将(替换为(),光标最终移到中间。
<script type="text/javascript">
$(document).ready(function () {
$("#d").keypress(function (e) {
var charTyped = String.fromCharCode(e.which);
if (charTyped == "{" || charTyped == "(") {
// Handle this case ourselves
e.preventDefault();
var sel = window.getSelection();
if (sel.rangeCount > 0) {
// First, delete the existing selection
var range = sel.getRangeAt(0);
range.deleteContents();
// Insert a text node with the braces/parens
var text = (charTyped == ")") ? "{}" : "()";
var textNode = document.createTextNode(text);
range.insertNode(textNode);
// Move the selection to the middle of the text node
range.setStart(textNode, 1);
range.setEnd(textNode, 1);
sel.removeAllRanges();
sel.addRange(range);
}
}
});
});
</script>
</head>
<body>
<div id="d" contentEditable="true">....</div>
</body>
</html>
$('div').keyup(function(){
//make here for loop which replace all emoticons
$(this).text().replace(':(', 'stupid.jpg');
});
发布未能找到该问题答案后我最终写的内容。我希望这对其他寻求答案的人有所帮助(:
我将发布一个更为通用的查找和替换解决方案(包含在一个类中)。这适用于内容可编辑的div,并且在用户键入时起作用,此外,它不会影响插入符号的位置。此实现使用不区分大小写的搜索(尽管在代码中禁用该搜索很简单)。它的另一个优点是,即使您在段落的中间(而不是仅在行的末尾)键入内容,它也可以使用,并且可以在粘贴的文本上使用。快去吧!
class FindAndReplace {
constructor($contentEditable, findAndReplaceData) {
var self = this;
$contentEditable.on('input blur', function () {
var textNodes = self.getTextNodes($contentEditable);
textNodes.each(function (i) {
// Perform all replacements on text
findAndReplaceData.forEach(function (findAndReplaceDatum) {
var find = findAndReplaceDatum.find;
var replace = findAndReplaceDatum.replace;
var regexEscapedFind = self.escapeRegExp(find);
var regexEscapedReplace = self.escapeRegExp(replace);
var regexEscapedCaseInsensitiveFind = self.makeRegexCaseInsensitive(regexEscapedFind);
// Case insensitive search for the find with a negative lookahead to check its not a case sensitive match of the replacement (aka to check its actually going to make a difference)
var regexString = `(?!${regexEscapedReplace})${regexEscapedCaseInsensitiveFind}`;
do {
// Get the latest version of the text node
textNode = self.getTextNodes($contentEditable)[i];
var text = textNode.data;
var regex = new RegExp(regexString);
var matchIndex = text.search(regex);
var matchFound = (matchIndex !== -1);
if (matchFound) {
// Select the match
var range = document.createRange();
range.setStart(textNode, matchIndex);
range.setEnd(textNode, matchIndex + find.length);
// Delete it
range.deleteContents();
// Create the replacement node
var textNode = document.createTextNode(replace);
// Insert it
range.insertNode(textNode);
// Set the range to the end of the selected node
range.collapse(false);
// Set the user selection the range
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
// Make sure there a no adjacent or empty text nodes
$contentEditable[0].normalize();
}
} while (matchFound)
});
});
});
}
escapeRegExp(string) {
// https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
getTextNodes($contentEditable) {
return $contentEditable.contents().filter(function () {
return this.nodeType == 3; // Text node
});
}
makeRegexCaseInsensitive(string) {
var stringArray = string.split('');
stringArray = stringArray.map(function (char) {
if (char.toLowerCase() !== char.toUpperCase())
return '[' + char.toLowerCase() + char.toUpperCase() + ']';
else
return char;
});
return stringArray.join('');
}
}
div {
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(function(){
var findAndReplaceData = [
{
'find': 'find me',
'replace': 'and replace with me!'
},
{
'find': 'foo',
'replace': 'bar'
},
{
'find': 'no',
'replace': 'yes'
}
];
$contentEditable = $('div');
new FindAndReplace($contentEditable,findAndReplaceData);
});
</script>
<div contenteditable="true"></div>