【问题标题】:How do I replace all hashtags in a contenteditable div with a hyperlink while ignoring previously replaced hashtags?如何在忽略以前替换的主题标签的同时用超链接替换 ​​contenteditable div 中的所有主题标签?
【发布时间】:2019-12-22 20:06:32
【问题描述】:

我正在构建一个标签转换器功能。每次用户单击输入或空间时,我都需要检查用户的文本中是否包含主题标签。我在这个正则表达式中使用了以前的答案:

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>&nbsp;").replace("<br>", ""); //replace hashtags with a link

      textField.html(currentCommentText);
   }
});

如果用户将每个唯一的主题标签都写一次,这会很好。但是,当用户键入两次相同的主题标签时,它也会在之前获取的主题标签前面添加链接。

如您所见,#sushi 和#pizza 后面有几个空格。如果我放大并检查为什么会发生这种情况:

您可以看到正则表达式并没有真正发挥作用。我听说使用正则表达式替换 html 不是很理想。有没有办法可以检查主题标签并仅替换文本中尚未转换的主题标签?

【问题讨论】:

    标签: jquery html replace hashtag


    【解决方案1】:

    选项 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>&nbsp;").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) - 这将导致它忽略已经存在的主题标签一个锚标记。然后,您必须替换替换字符串以包含第二个匹配组 ($2)。

    $(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=#>$2</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>

    【讨论】:

    • 这不适用于这个字符串:“#hashtag#hashtag”最后一个#hashtag也应该匹配
    • @IT-Girl - 选项一适用于该用例。这就是为什么我选择了它。
    • 选项 1 不起作用,因为它会删除文本中的所有 html。包括以前添加的主题标签。这是一个多次触发的函数。每次用户按回车键或空格键时都会触发它。除了我的元素之外,还有一个 contenteditable div,它包含的 html 不仅仅是主题标签。
    • @IT-Girl - 这是应该包含在问题中的信息。我是一名志愿者,我花时间在你的问题上得到的唯一报酬就是你的选票。通常我会很乐意修改我的答案,但是在你证明你将把我的投票作为人质直到我写出你想要的确切代码之后,我真的没有动力继续尝试帮助你。所以。不是免费的代码编写服务。如果您想雇用我来帮助您的项目,我的联系信息在我的个人资料中。祝你好运。
    • 我没有扣押你的赞成票。我只是说您的代码对我的问题没有帮助,这就是为什么我删除了我最初的支持。我找到了解决方案并将其添加到我的问题中,以便您了解它为什么不起作用。
    【解决方案2】:

    此正则表达式查找尚未包含在超链接中的所有主题标签。它还创建了两个组,我们可以使用它们来形成主题标签的链接。 https://regex101.com/r/EUNySg/13

    /(?!\s*#\w+\s*<\/a>)(#(\w+))/g
    

    JQuery

    $(document).on("keyup", ".post-input-field", function (event) {
       if (event.keyCode === 32 || event.keyCode === 13) {
          let html = $(this).html();
          html = html.replace( /(?!\s*#\w+\s*<\/a>)(#(\w+))/g, "<a class='hashtag' href='https://google.com/$1'>$2</a>&nbsp;").replace("<br>", ""); 
          $(this).html(html);
       }
    });
    

    您可以在下面看到所有#hashtag 都被突出显示,但#notahashtag 没有被突出显示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-17
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      • 2013-06-19
      • 1970-01-01
      相关资源
      最近更新 更多