如何在忽略之前替换的主题标签的同时,用超链接替换内容可编辑的 div 中的所有主题标签?
How do I replace all hashtags in a contenteditable div with a hyperlink while ignoring previously replaced hashtags?
我正在构建主题标签转换器功能。每次用户点击输入或 space 时,我都需要检查用户的文本中是否有主题标签。我用这个正则表达式使用了以前的答案:
HTML
<div class="post-input-field" contenteditable="true">My favourite dish is <a href=#>#sushi</a>#but I also like #pizza. </div>
JQuery
/**
* Trigger when someone releases a key on the field where you can post remarks, posts or reactions
*/
$(document).on("keyup", ".post-input-field", function (event) {
// if the user has pressed the spacebar (32) or the enter key (13)
if (event.keyCode === 32 || event.keyCode === 13) {
currentCommentText = currentCommentText.replace(/#(\w+)/g, "<a class='hashtag' href=" + url + " target='_blank'>$&</a> ").replace("<br>", ""); //replace hashtags with a link
textField.html(currentCommentText);
}
});
如果用户将每个唯一的主题标签都写一次,这就可以正常工作。但是,当用户两次键入相同的主题标签时,它也会在先前获取的主题标签前面添加 link。
如您所见,#sushi 和#pizza 后面有几个 space。如果我放大并检查为什么会发生这种情况:
您可以看到正则表达式并没有真正发挥作用。我听说使用正则表达式替换 html 不是很理想。有没有办法检查话题标签,只替换文本中尚未转换的话题标签?
选项 1:
在再次进行替换之前从字符串中删除 HTML。只需将 HTML 放入空白 div 中,然后从中取出文本。
$(document).on("keyup", ".post-input-field", function (event) {
if (event.keyCode === 32 || event.keyCode === 13) {
var val = $(this).val();
// strip html from val
val = $('<div>').html(val).text();
val = val.replace(/#(\w+)/g, "<a class='hashtag' href=#>$&</a> ").replace("<br>", "");
$(this).val(val);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea class="post-input-field" contenteditable="true"></textarea>
选项 2:
以 (^|\s)
开始您的模式,这将仅匹配行开头的主题标签 (^
) 或跟随一些空格的主题标签 (\s
) - 这将导致它忽略已经在锚标记中的主题标签。然后,您必须替换替换字符串以包含第二个匹配组 (</code>)。</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre><code>$(document).on("keyup", ".post-input-field", function (event) {
if (event.keyCode === 32 || event.keyCode === 13) {
var val = $(this).val();
val = val.replace(/(^|\s)(#\w+)/g, " <a href=#></a>").replace("<br>", "");
$(this).val(val);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea class="post-input-field" contenteditable="true"></textarea>
我正在构建主题标签转换器功能。每次用户点击输入或 space 时,我都需要检查用户的文本中是否有主题标签。我用这个正则表达式使用了以前的答案:
HTML
<div class="post-input-field" contenteditable="true">My favourite dish is <a href=#>#sushi</a>#but I also like #pizza. </div>
JQuery
/**
* Trigger when someone releases a key on the field where you can post remarks, posts or reactions
*/
$(document).on("keyup", ".post-input-field", function (event) {
// if the user has pressed the spacebar (32) or the enter key (13)
if (event.keyCode === 32 || event.keyCode === 13) {
currentCommentText = currentCommentText.replace(/#(\w+)/g, "<a class='hashtag' href=" + url + " target='_blank'>$&</a> ").replace("<br>", ""); //replace hashtags with a link
textField.html(currentCommentText);
}
});
如果用户将每个唯一的主题标签都写一次,这就可以正常工作。但是,当用户两次键入相同的主题标签时,它也会在先前获取的主题标签前面添加 link。
您可以看到正则表达式并没有真正发挥作用。我听说使用正则表达式替换 html 不是很理想。有没有办法检查话题标签,只替换文本中尚未转换的话题标签?
选项 1:
在再次进行替换之前从字符串中删除 HTML。只需将 HTML 放入空白 div 中,然后从中取出文本。
$(document).on("keyup", ".post-input-field", function (event) {
if (event.keyCode === 32 || event.keyCode === 13) {
var val = $(this).val();
// strip html from val
val = $('<div>').html(val).text();
val = val.replace(/#(\w+)/g, "<a class='hashtag' href=#>$&</a> ").replace("<br>", "");
$(this).val(val);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea class="post-input-field" contenteditable="true"></textarea>
选项 2:
以 (^|\s)
开始您的模式,这将仅匹配行开头的主题标签 (^
) 或跟随一些空格的主题标签 (\s
) - 这将导致它忽略已经在锚标记中的主题标签。然后,您必须替换替换字符串以包含第二个匹配组 (</code>)。</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre><code>$(document).on("keyup", ".post-input-field", function (event) {
if (event.keyCode === 32 || event.keyCode === 13) {
var val = $(this).val();
val = val.replace(/(^|\s)(#\w+)/g, " <a href=#></a>").replace("<br>", "");
$(this).val(val);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea class="post-input-field" contenteditable="true"></textarea>