当字符串与键/值对中的键(与其对应的值)匹配时替换字符串

时间:2011-08-11 01:35:36

标签: javascript jquery replace key

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

例如,在像这样的句子中,WHO eLENA澄清了有关拯救生命的营养干预的指导,并协助扩大营养不良的行动, WHOeLENA将两者都包含在<abbr>标记中。我想要title属性来显示缩写的扩展版本;即WHO = World Health Organization

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

3 个答案:

答案 0 :(得分:1)

首先,你必须准确确定用于选择替代品的标准 - 我建议在字边界上进行,这样“我与世界卫生组织合作”将把“世界卫生组织”包装成abbr,但是“WHOEVER TOUCHED”我的自行车将注册它“不会缩写”WHO“。你还应该决定你是否会区分大小写(可能你想成为,所以“刚进来的那个人”不会缩写为“who”。)

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

答案 1 :(得分:1)

首先,这应该在服务器上完成,在客户端上执行它是非常低效的并且更容易出错。但是说了......

你可以尝试处理元素的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>

使用分词模式来分割单词很有意思,因为在“与非北约力量”这样的字符串中,单词NATO仍将被包裹但不是“非”部分。但是,如果缩写跨文本节点或连字符分开,则除非在 abbrs 对象中包含相同的属性名称,否则将无法识别缩写。

答案 2 :(得分:0)

查看javascript replace method

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

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

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

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