【问题标题】:Replace string when it matches a key in a key/value pair (with its corresponding value)当字符串与键/值对中的键匹配时替换字符串(与其对应的值)
【发布时间】:2011-08-11 01:35:36
【问题描述】:

我正在尝试使用javascript/jQuery 将段落中的任何缩写包装在<abbr title=""> 标记中。

例如,在这样的句子中,WHO eLENA 阐明了关于拯救生命的营养干预措施的指导,并协助扩大针对营养不良的行动, WHOeLENA 都将被包装在<abbr> 标签中。我希望标题属性显示缩写的扩展版本;即WHO = World Health Organization

实现这一点的最佳方法是什么?我对javascript/jQuery 有点陌生,所以我在这里在黑暗中摆弄。到目前为止,我已经创建了一个变量,其中包含所有作为键/值对的缩写,我可以替换缩写的特定实例,但仅此而已。

【问题讨论】:

  • 你是如何存储你的键值对的?
  • 像这样; var abbrs = { 'WHO': '世界卫生组织', 'NATO': '北大西洋公约组织' };

标签: javascript jquery replace key


【解决方案1】:

首先,您必须确定将使用什么标准来选择替代品——我建议在单词边界上进行,这样“I work with WHO”会将“WHO”包装在缩写中,但“WHOEVER TOUCHED MY BIKE WILL REGRET IT”不会缩写为“WHO”。您还应该决定是否要区分大小写(可能是您想要的,这样“刚进来的人”就不会缩写为“谁”。)

  1. 使用 jQuery 对文档中的所有文本进行递归。这可以使用.children 选择器并逐步浏览元素并阅读所有文本来完成。
  2. 对于每个文本节点,将文本拆分为单词。
  3. 对于每个单词,在您的键值存储中查找它以查看它是否与某个键匹配。如果是,则获取该值,并构造一个新元素<abbr title="value">key</abbr>
  4. 将文本节点分解为 a) 缩写之前的文本(文本节点)、b) 缩写本身(一个元素)和 c) 缩写之后的文本(文本节点)。将所有三个作为原始文本节点的父节点的子节点插入,替换原始文本节点。

这些步骤中的每一个都需要一些工作并查找一些 API 文档,但这是基本过程。

【讨论】:

  • 嘿,谢谢你的开始——我永远不会真正使用“WHO”(或其他可以用作单词或单词的缩写),但你提出的问题正是我希望听到。
【解决方案2】:

首先,这确实应该在服务器上完成,在客户端上执行效率非常低,而且更容易出错。不过话说回来……

您可以尝试处理元素的 innerHTML,但 javascript 和正则表达式在这方面确实很糟糕。

最好的方法是使用 DOM 方法并解析每个元素的文本。当找到匹配的单词时,将其替换为 abbr 元素。这要求在文本节点中找到匹配项时,替换整个节点,因为一个文本节点现在将是 abbr 元素两侧的两个(或更多)文本节点。

这是一个简单的函数,但它可能存在您需要解决的弱点。它适用于简单的文本字符串,但您需要在更复杂的字符串上对其进行彻底测试。自然,它应该只在特定节点上运行一次,否则缩写将被双重包装。

var addAbbrHelp = (function() {
  var abbrs = {
      'WHO': 'World Health Organisation', 
      'NATO': 'North Atlantic Treaty Organisation'
  };

  return function(el) {
    var node, nodes = el.childNodes;
    var word, words;
    var adding, text, frag;
    var abbr, oAbbr = document.createElement('abbr');
    var frag, oFrag = document.createDocumentFragment()

    for (var i=0, iLen=nodes.length; i<iLen; i++) {
      node = nodes[i];

      if (node.nodeType == 3) { // if text node
        words = node.data.split(/\b/);
        adding = false;
        text = '';
        frag = oFrag.cloneNode(false);

        for (var j=0, jLen=words.length; j<jLen; j++) {
          word = words[j];

          if (word in abbrs) {
            adding = true;

            // Add the text gathered so far
            frag.appendChild(document.createTextNode(text));
            text = '';

            // Add the wrapped word
            abbr = oAbbr.cloneNode(false);
            abbr.title = abbrs[word];
            abbr.appendChild(document.createTextNode(word));
            frag.appendChild(abbr);

          // Otherwise collect the words processed so far
          } else {
            text += word;
          }
        }

        // If found some abbrs, replace the text 
        // Otherwise, do nothing
        if (adding) {
         frag.appendChild(document.createTextNode(text));
         node.parentNode.replaceChild(frag, node);
        }

      // If found another element, add abbreviation help
      // to its content too
      } else if (node.nodeType == 1) {
        addAbbrHelp(node);
      }
    }
  }
}());

对于标记:

<div id="d0">
  <p>This is the WHO and NATO string.</p>
  <p>Some non-NATO forces were involved.</p>
</div>

并调用:

addAbbrHelp(document.getElementById('d0'));

导致(我的格式):

<div id="d0">
  <p>This is the<abbr title="World Health Organisation">WHO</abbr>
  and <abbr title="North Atlantic Treaty Organisation">NATO</abbr>
  string.</p>
  <p>Some non-<abbr title="North Atlantic Treaty Organisation">NATO</abbr> forces were involved.</p>
</div>

使用分词模式来拆分单词很有趣,因为在像“with non-NATO force”这样的字符串中,NATO 这个词仍然会被包裹,但“non-”部分不会。但是,如果缩写在文本节点或连字符之间分割,除非在 abbrs 对象中包含相同的模式作为属性名称,否则将无法识别它。

【讨论】:

    【解决方案3】:

    查看 javascript replace method

    我会使用 JQuery 提取段落中的所有文本

    var text = $(p#paragraphId).html()

    使用 for 循环遍历您拥有的缩写列表,然后使用上面提到的 replace() 方法将缩写替换为您需要的标记。

    最后使用 JQuery 将段落的 html 设置回你新更新的字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      • 2016-07-12
      • 1970-01-01
      相关资源
      最近更新 更多