【问题标题】:Slow highlighting in Firefox在 Firefox 中缓慢突出显示
【发布时间】:2012-09-12 09:42:58
【问题描述】:

我们需要为html页面中的一些关键字/句子添加锚点和高亮。事实证明,在 Firefox 中突出显示真的很慢。

在下面的代码中,所有需要高亮的范围都存储在数组hiliteRanges中:

for (var i = 0; i < hiliteRanges.length; i++){
    document.designMode = "on";

    var selHilites = window.getSelection();

    if (selHilites.rangeCount > 0)
        selHilites.removeAllRanges();

    selHilites.addRange(hiliteRanges[i]);

    var anchorId = 'index'+i;
    var insertedHTML = '<span id="' + anchorId + '" style="background-color: #FF8C00;" >'+hiliteRanges[i].toString()+'</span>';

    document.execCommand('inserthtml', false, insertedHTML);                                                                                    
    document.designMode = "off";
}

有什么方法可以加快处理速度吗?我们可以在数组hiliteRanges 中有数百个范围。我们曾经尝试将designMode 设置移到循环之外,但我们可以看到循环运行时html页面中的某些部分是可编辑的。

【问题讨论】:

  • 相关:Javascript: document.execCommand cross-browser? 为什么不用contentEditable?或者这是否与designMode 方法有关?
  • 这是对您正在做的事情的适当演示吗? jsfiddle.net/userdude/cHCcm/1
  • 其实我是先用FF的window.find方法搜索关键字,把所有选中的范围存入数组hiliteRanges。然后我想在 FF 中突出显示所有这些选定的范围。我可以在这些选定的范围内使用 contentEditable 吗?
  • firefox 上的 javascript 引擎比 ie 和 chrome 都慢,你遇到的问题纯粹是处理太多。将尽可能多的代码移到 for 循环之外,并尽可能地重构代码。
  • @SaintGerbil 这与 JavaScript 无关;真正的问题是反复打开和关闭所有编辑机器。另外要注意的是,Firefox 中的 JS 引擎实际上比 IE 更快,并且与 Chrome 差不多,这取决于你用它做什么。

标签: javascript html firefox range highlighting


【解决方案1】:

这是我的默认突出显示 sn-p 并且在每个浏览器中都可以正常工作。试试看。

演示: http://jsbin.com/adeneh/1/edit

function highlight(text, words, tag) {

  // Default tag if no tag is provided
  tag = tag || 'span';

  var i, len = words.length, re;
  for (i = 0; i < len; i++) {
    // Global regex to highlight all matches
    re = new RegExp(words[i], 'g');
    if (re.test(text)) {
      text = text.replace(re, '<'+ tag +' class="highlight">$&</'+ tag +'>');
    }
  }

  return text;
}

// Usage:
var el = document.getElementById('element');
el.innerHTML = highlight(
  el.innerHTML, 
  ['word1', 'word2', 'phrase one', 'phrase two', ...]
);

并取消突出显示:

function unhighlight(text, tag) {
  // Default tag if no tag is provided
  tag = tag || 'span';
  var re = new RegExp('(<'+ tag +'.+?>|<\/'+ tag +'>)', 'g');
  return text.replace(re, '');
}

【讨论】:

  • 谢谢。但是该数组包含所有选定的范围,这些范围是使用 window.find 方法收集的,而不是字符串。
  • 从数据中创建一个字符串数组应该不会太难。
  • 是的。也许只需要获取每个范围的 parentElement,然后替换它的 innerHTML。修改会影响其他范围吗?我不确定这些范围的位置是否会被弄乱......如果是这样,父元素就会出错。例如,如果我们更改范围 hiliteRanges[0] 的容器的 innerHTML,我们仍然可以获得范围 hiliteRanges[1000] 的正确容器吗?基本上数组 hiliteRanges 中的范围是随机的...
  • window.find() 方法的优点是可以匹配跨越元素边界的文本,而这种方法无法做到这一点。但是,window.find() 将来可能会消失:bugzilla.mozilla.org/show_bug.cgi?id=672395
  • 选择find()方法的好处是我们不用担心html标签和js标签。查找/搜索关键字要容易得多。不希望它消失...
【解决方案2】:

没有必要为此使用document.execCommand()。改用范围方法就行了,就不用designMode了。

var anchorId, hiliteTextNode, hiliteSpan;
for (var i = 0; i < hiliteRanges.length; i++){
    // Create the highlight element
    hiliteSpan = document.createElement("span");
    hiliteSpan.id = anchorId;
    hiliteSpan.style.backgroundColor = "#FF8C00";

    hiliteTextNode = document.createTextNode(hiliteRanges[i].toString());
    hiliteSpan.appendChild(hiliteTextNode);

    // Replace the range content
    hiliteRanges[i].deleteContents();
    hiliteRanges[i].insertNode(hiliteSpan);
}

另外,由于范围受到 DOM 突变的影响,我建议您在使用window.find() 收集范围的同时执行此部分。这是一个例子:

http://jsfiddle.net/YgFjT/

【讨论】:

  • 这个解决方案看起来很有希望。我现在就试试。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 2013-11-19
  • 1970-01-01
  • 2015-04-24
  • 1970-01-01
相关资源
最近更新 更多