简体   繁体   English

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

[英]Replace string when it matches a key in a key/value pair (with its corresponding value)

I'm trying to use javascript / jQuery to wrap any abbreviations in a paragraph in a <abbr title=""> tag.我正在尝试使用javascript / jQuery将任何缩写包装在<abbr title="">标记中的段落中。

For example, in a sentence like, The WHO eLENA clarifies guidance on life-saving nutrition interventions, and assists in scaling up action against malnutrition, WHO and eLENA would both be wrapped in an <abbr> tag.例如,在“WHO eLENA 阐明了关于拯救生命的营养干预措施的指导,并协助扩大针对营养不良的行动”这样的句子中, WHOeLENA都将被包装在<abbr>标记中。 I'd like the title attribute to display the extended version of the abbreviation;我希望标题属性显示缩写的扩展版本; ie WHO = World Health Organization .WHO = World Health Organization

Whats the best way of accomplishing this?实现这一目标的最佳方法是什么? I'm a bit new to javascript / jQuery so I'm fiddling in the dark here.我对javascript / jQuery有点陌生,所以我在这里在黑暗中摆弄。 So far I've created a variable that contains all the abbreviations as key/value pairs, and I can replace a specific instance of an abbreviation, but not much else.到目前为止,我已经创建了一个变量,其中包含所有作为键/值对的缩写,并且我可以替换缩写的特定实例,但仅此而已。

First you must decide exactly what criteria you will use for selecting a replacement -- I would suggest doing it on a word boundary, such that "I work with WHO" will wrap "WHO" in an abbr, but "WHOEVER TOUCHED MY BIKE WILL REGRET IT" won't abbreviate "WHO".首先,您必须确定将使用什么标准来选择替代品——我建议在单词边界上进行,这样“我与 WHO 合作”将把“WHO”包装在缩写中,但“WHOEVER TOUCED MY BIKE WILL REGRET IT”不会缩写为“WHO”。 You should also decide if you are going to be case sensitive (probably you want to be, so that "The guy who just came in" doesn't abbreviate "who".)您还应该决定是否要区分大小写(可能是您想要的,这样“刚进来的人”就不会缩写“谁”。)

  1. Use jQuery to recurse over all of the text in the document.使用 jQuery 递归文档中的所有文本。 This can be done using the .children selector and stepping through elements and reading all the text.这可以使用.children选择器并单步执行元素并阅读所有文本来完成。
  2. For each text node, split the text into words.对于每个文本节点,将文本拆分为单词。
  3. For each word, look it up in your key value store to see if it matches a key.对于每个单词,在您的键值存储中查找它以查看它是否与键匹配。 If so, get the value, and construct a new element <abbr title="value">key</abbr> .如果是,获取值,并构造一个新元素<abbr title="value">key</abbr>
  4. Break up the text node into a) the text before the abbreviation (a text node), b) the abbreviation itself (an element), and c) the text after the abbreviation (a text node).将文本节点分解为 a) 缩写之前的文本(文本节点)、b) 缩写本身(元素)和 c) 缩写之后的文本(文本节点)。 Insert all three as child nodes of the original text node's parent, replacing the original text node.插入所有三个作为原始文本节点的父节点的子节点,替换原始文本节点。

Each of these steps will require a bit of work and looking up some API docs, but that is the basic process.这些步骤中的每一个都需要一些工作并查找一些 API 文档,但这是基本过程。

Firstly, this should really be done on the server, doing it on the client is very inefficient and much more prone to error.首先,这确实应该在服务器上完成,在客户端上执行效率非常低,而且更容易出错。 But having said that...不过话说回来……

You can try processing the innerHTML of the element, but javascript and regular expressions are really bad at that.您可以尝试处理元素的 innerHTML,但 javascript 和正则表达式在这方面真的很糟糕。

The best way is to use DOM methods and parse the text of each element.最好的方法是使用 DOM 方法并解析每个元素的文本。 When a matching word is found, replace it with an abbr element.当找到匹配的单词时,将其替换为 abbr 元素。 This requires that where a match is found in a text node, the entire node is replaced because what was one text node will now be two text nodes (or more) either side of an abbr element.这要求在文本节点中找到匹配项时,替换整个节点,因为一个文本节点现在将是 abbr 元素两侧的两个(或更多)文本节点。

Here is a simple function that goes close, but it likely has foibles that you need to address.这是一个简单的 function 接近,但它可能有您需要解决的弱点。 It works on simple text strings, but you'll need to test it thoroughly on more complex strings.它适用于简单的文本字符串,但您需要在更复杂的字符串上对其进行彻底测试。 Naturally it should only ever be run once on a particular node or abbreviations will be doubly wrapped.自然,它应该只在特定节点上运行一次,否则缩写将被双重包装。

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);
      }
    }
  }
}());

For the markup:对于标记:

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

and calling:并调用:

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

results in (my formatting):结果(我的格式):

<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>

Using the word break pattern to split words is interesting because in strings like "with non–NATO forces", the word NATO will still get wrapped but not the "non–" part.使用分词模式来拆分单词很有趣,因为在像“with non-NATO force”这样的字符串中,NATO 这个词仍然会被包裹,但“non-”部分不会。 However, if the abbreviation is split across a text node or by a hyphen, it will not be recognised unless the same pattern is included as a property name in the abbrs object.但是,如果缩写在文本节点或连字符之间分割,除非在缩写 object中包含相同的模式作为属性名称,否则它不会被识别。

Check out the javascript replace method .查看 javascript替换方法

I'd use JQuery to pull out all the text in the paragraph我会使用 JQuery 拉出段落中的所有文本

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

Use a for loop to loop through the list of abbreviations you have and then use the replace() method mentioned above to swap out the abbreviation for the tag you need.使用 for 循环遍历您拥有的缩写列表,然后使用上面提到的 replace() 方法将缩写替换为您需要的标记。

Finally use JQuery to set the html of the paragraph back to your newly updated string.最后使用 JQuery 将段落的 html 设置回您新更新的字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM