用纯jQuery即时替换内容中的文本

问题描述 投票:3回答:3

我在StackOverflow上看到了一些有关此的问题,但是似乎很难找到基于jQuery的解决方案。因此,我想问这个问题。

我想用属性div即时替换contenteditable="true"内的文本。

我正在寻找一个基于jQuery的解决方案,该解决方案将执行以下操作:

  • 自动实时替换书写的文字(键入时)
  • 能够继续写入(替换完成时)

我看过SC编辑器(http://www.sceditor.com/),似乎确实做到了这一点(例如,如果您尝试键入:),它将被表情符号代替。

我认为一个好的开始是将所有元素替换为一个数组:

$.settings = {
    path: 'https://example.com/images/',
    emoticons: {
        ':(' : 'stupid.jpg',
        ':)' : 'smart.jpg',
    }
}

我一直找不到很好的例子。如果有人可以分享他们的想法和与此相关的任何代码,将非常高兴。

如何使用上述代码以最佳的方式完成替换?

javascript jquery contenteditable
3个回答
0
投票

我发现了这个。如果进行调整,它可能会满足您的需求。它将{替换为{},将(替换为(),光标最终移到中间。

    <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>

0
投票
$('div').keyup(function(){
    //make here for loop which replace all emoticons
    $(this).text().replace(':(', 'stupid.jpg');
});

0
投票

发布未能找到该问题答案后我最终写的内容。我希望这对其他寻求答案的人有所帮助(:

我将发布一个更为通用的查找和替换解决方案(包含在一个类中)。这适用于内容可编辑的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>
© www.soinside.com 2019 - 2024. All rights reserved.