javascript - JS - 查找字符串的所有实例并包裹在 anchor 标记中

标签 javascript html

我试图弄清楚是否可以用 anchor 标记包装字符串的所有实例。

基本上在我们的网站上我想找到 myBrand 的任何实例或myBrand.com并将它们包裹在像<a href="/">myBrand</a>这样的 anchor 中或<a href="/">myBrand.com</a> .

但是,我希望能够找到所有此类实例,无论它们在我页面上的各个元素中埋藏多深,并查看它们是否已链接,这就是我遇到问题的地方。

编辑

我已将代码片段编辑为现在的内容,但仍然遇到困难:

document.querySelectorAll('body').forEach(function(el){
  var text = el.innerHTML.match(/myBrand/g);
  
  console.log(text.parentElement); // how do i get the parent?
  
  if(isAnchor(text.parentElement)){
    //
  }else{
      var newtext = el.innerHTML.replace(/myBrand/g, '<a href="/">myBrand</a>');
    el.innerHTML = newtext;
  }
});

function isAnchor(str){
    return /^\<a.*\>.*\<\/a\>/i.test(str);
}
<body>

myBrand

<h1>myBrand.com</h1>

<p>This is a div that mentions myBrand</p>

<table>
<thead>
    <tr>
    <td>This is myBrand's table header</td>
    </tr>
</thead>
<tbody>
  <tr>
  <td>myBrand.com</td>
  </tr>
</tbody>
</table>

<a href="/">myBrand.com</a>

</body>

最佳答案

使用innerHTML替换html内容的一个问题是,一旦使用innerHTML设置新的html,分配给现有元素的任何数据或事件都将被删除。在 document.body 级别执行此操作是一个非常糟糕的主意。

因此,我编写了一个使用文本节点的解决方案。文本节点不能有事件,因此删除文本节点并添加新节点不会产生任何副作用(选择除外,在这种情况下我们可以忽略它)。

function iterateTextNodes(container, callback) {
    Array.from(container.childNodes).forEach(node => {
        if (node.nodeType === node.TEXT_NODE) {
            callback(node);
        } else if (node.tagName !== 'A') {
            /* Do not go inside anchor tags checking for text nodes,
               this get rids of the problem with nodes that are already
               inside anchor tags */
            iterateTextNodes(node, callback);
        }
    });
}

function getAnchor(href, content) {
    const anchor = document.createElement('A');
    anchor.appendChild(document.createTextNode(content));
    anchor.setAttribute('href', href);
    return anchor;
}

iterateTextNodes(document.body, function (node) {
    const parentNode = node.parentNode;
    // Check for myBrand.com first and then check for myBrand, to handle all the cases
    node.nodeValue.split('myBrand.com').forEach((string, i) => {
        i && parentNode.insertBefore(getAnchor('/', 'myBrand.com'), node);
        string.split('myBrand').forEach((string, i) => {
            i && parentNode.insertBefore(getAnchor('/', 'myBrand'), node);
            parentNode.insertBefore(document.createTextNode(string), node);
        });
    });
    parentNode.removeChild(node);
});
<body>

myBrand

<h1>myBrand.com</h1>

<p>This is a div that mentions myBrand</p>

<table>
<thead>
    <tr>
    <td>This is myBrand's table header</td>
    </tr>
</thead>
<tbody>
  <tr>
  <td>myBrand.com</td>
  </tr>
</tbody>
</table>

<a href="/">myBrand.com</a>

</body>

关于javascript - JS - 查找字符串的所有实例并包裹在 anchor 标记中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55965532/

相关文章:

javascript - 如何将 "push notifications"发送到特定用户网页?

javascript - 如何在 React Native 的多子父 View 中将一个子垂直居中

javascript - 使用 jQuery 根据所选数据获取参数并将其放入 url

javascript - 单击具有字符串名称的一个类以激活另一个类

javascript - 如何隐藏和显示选择选项

javascript - XMLHttpRequest 无法加载。仅在 POST 调用且仅通过实际本地网站时无 Access-Control-Allow-Origin

javascript - 在不同的选择框上更改选择框值

html - HTML Canvas 中的原始形状库

javascript - 如何使用 .nextUntil 将两个不同的类添加到 <h2> 元素列表中

html - 如何将图像放入没有空格的框中