Codemirror 2.2 清除所有标记

发布于 2024-12-28 20:31:25 字数 249 浏览 2 评论 0原文

我正在寻找清除代码镜像文本的所有标记。标记已创建,调用

ret = codemirror.markText(..);
histMarks.push(ret);

要删除所有标记,我们将单独清除每个标记:

foreach( histMarks, i.clear() );  // this is pseudocode

是否有更有效的方法来删除所有标记?

I'm looking to clear all marks to a codemirror text. The marks have been created calling

ret = codemirror.markText(..);
histMarks.push(ret);

To delete all marks we're clearing each one individually:

foreach( histMarks, i.clear() );  // this is pseudocode

Is there a more efficient way to delete all marks ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

怪我入戏太深 2025-01-04 20:31:25

如果您确实正在寻找“clearAllMarks”类型的功能,那么有一种稍微更有效的方法。您甚至被迫自己捕获所有标记并将其存储在数组中的全部原因是因为它们没有存储在 codemirror 实例中的任何位置。这表明他们在 .clear 上所做的任何事情都是独立的(也就是说,每个 TextMarker 都拥有存储在其自身上进行清除所需的所有信息。)。确定后,我们可以看一下 markText() 和 .clear 函数:

function markText(from, to, className, options) {
      from = clipPos(from); to = clipPos(to);
      var marker = new TextMarker("range", className);
      if (options) for (var opt in options) if (options.hasOwnProperty(opt))
        marker[opt] = options[opt];
      var curLine = from.line;
      doc.iter(curLine, to.line + 1, function(line) {
        var span = {from: curLine == from.line ? from.ch : null,
                    to: curLine == to.line ? to.ch : null,
                    marker: marker};
        line.markedSpans = (line.markedSpans || []).concat([span]);
        marker.lines.push(line);
        ++curLine;
      });
      changes.push({from: from.line, to: to.line + 1});
      return marker;
    }
TextMarker.prototype.clear = operation(function() {
      var min, max;
      for (var i = 0; i < this.lines.length; ++i) {
        var line = this.lines[i];
        var span = getMarkedSpanFor(line.markedSpans, this);
        if (span.from != null) min = lineNo(line);
        if (span.to != null) max = lineNo(line);
        line.markedSpans = removeMarkedSpan(line.markedSpans, span);
      }
      if (min != null) changes.push({from: min, to: max + 1});
      this.lines.length = 0;
      this.explicitlyCleared = true;
    });

我没有包含所有代码,因此请自行仔细阅读(codemirror.js),
但你应该注意到的是,所有方法真正做的就是确保如果你调用clear,它会从正确的位置删除标记,因为没有理由你不能将相同的css类添加到不同的位置使用不同标记的行...并且清除一个标记不应同时清除两者。该方法还更新更改数组,该数组只是更改了哪些行的记录。

由于我们正在执行“全部清除”操作,因此我们并不真正关心删除某些内容而不是其他内容,因此不需要计算标记影响范围内的内容。另外,因为 markText 没有副作用,所以没有其他需要重置的内容,所以本质上您所做的就是删除 css 类。

因此,为了稍微更快地清除,您仍然必须存储标记或使用标记应用的类,以便您可以依次执行以下操作之一:

如果您仍然存储标记:

for (var i = 0;i<markers.length;i++)
    $('.handleToCodeMirrorEditor').removeClass(markers[i].style);

如果您只存储类:

$('.handleToCodeMirrorEditor').removeClass(classes.join(" "));

基准测试:虽然我很清楚有效的基准测试通常是一项棘手的任务,但我认为至少对各种方法进行一些测试是值得的。
我设置了一个测试,其中添加了一定数量的标记,每个标记应用不同的类(按索引递增)。然后,我运行并计时了 3 种不同的方法来单独删除这些标记。我以不同的顺序多次运行每个测试,以确保结果一致。
我比较了 3 种方法:

  • 存储标记并在每种方法上调用清除。
  • 存储标记并根据每个特定对象调用removeClass
    style
  • 存储样式并对所有样式调用removeClass (classes.join(" "))。

对于 100 个标记,删除结果如下:

297ms .clear
160ms .removeClass on each markerStyle
153ms .removeClass single call

对于 1000 个标记:

4891ms .clear
2677ms .removeClass on each markerStyle
2572ms .removeClass single call

There is a slightly more efficient way if you are truly looking for a "clearAllMarks" sort of functionality. The whole reason you are are even forced to capture and store all the marks yourself in the array is because they are not stored anywhere within a codemirror instance. This indicates that whatever they are doing on .clear is self-contained (that is to say that each TextMarker has all the information it needs to do the clearing stored on itself.). With that determined we can take a look at the markText() and the .clear function:

function markText(from, to, className, options) {
      from = clipPos(from); to = clipPos(to);
      var marker = new TextMarker("range", className);
      if (options) for (var opt in options) if (options.hasOwnProperty(opt))
        marker[opt] = options[opt];
      var curLine = from.line;
      doc.iter(curLine, to.line + 1, function(line) {
        var span = {from: curLine == from.line ? from.ch : null,
                    to: curLine == to.line ? to.ch : null,
                    marker: marker};
        line.markedSpans = (line.markedSpans || []).concat([span]);
        marker.lines.push(line);
        ++curLine;
      });
      changes.push({from: from.line, to: to.line + 1});
      return marker;
    }
TextMarker.prototype.clear = operation(function() {
      var min, max;
      for (var i = 0; i < this.lines.length; ++i) {
        var line = this.lines[i];
        var span = getMarkedSpanFor(line.markedSpans, this);
        if (span.from != null) min = lineNo(line);
        if (span.to != null) max = lineNo(line);
        line.markedSpans = removeMarkedSpan(line.markedSpans, span);
      }
      if (min != null) changes.push({from: min, to: max + 1});
      this.lines.length = 0;
      this.explicitlyCleared = true;
    });

I haven't included all the code so feel free to peruse it yourself (codemirror.js),
but what you should notice is that all the method is really doing is the work to ensure that if you are calling clear it removes the markers from the correct places as there is no reason why you couldn't have added the same css class to different lines using different markers...and clearing one shouldn't clear both. The method also updates the changes array which is just a record of what lines were changed.

Since we are doing a "clear all" we don't really care about removing some and not others, so the work of figuring out what spans the marker affects isn't necessary. Also, because there are no side affects of markText there is nothing else to reset, so at its heart all you are doing is removing css classes.

Thus, for a slightly faster clear you would still have to either store the markers or the classes you applied using markers so you could in turn do one of the following:

If you still store the markers:

for (var i = 0;i<markers.length;i++)
    $('.handleToCodeMirrorEditor').removeClass(markers[i].style);

If you just store the classes:

$('.handleToCodeMirrorEditor').removeClass(classes.join(" "));

Benchmarking: While I am well aware that effective benchmarking can often be a tricky task, I figured it would be worthwhile to at least run few tests of various methodologies.
I setup a test where I added a certain number of markers each applying a different class (incremented by index). I then ran and timed 3 different methods for removing those markers each in isolation. I ran each test a number of times in varied order to ensure consistent results.
I compared 3 methods:

  • storing the markers and calling clear on each one.
  • Storing the marking and calling removeClass on each one's specific
    style
  • Storing the styles and calling removeClass on all styles (classes.join(" ")).

For 100 markers to remove the results were as follows:

297ms .clear
160ms .removeClass on each markerStyle
153ms .removeClass single call

For 1000 markers:

4891ms .clear
2677ms .removeClass on each markerStyle
2572ms .removeClass single call
樱娆 2025-01-04 20:31:25

最干净的解决方案是提取所有标记,然后清除它们

editor.doc.getAllMarks().forEach(marker => marker.clear());

,或者在上面的情况下

this.instance.doc.getAllMarks().forEach(marker => marker.clear());

The cleanest solution would be to extract all the marks, and then clear them

editor.doc.getAllMarks().forEach(marker => marker.clear());

or in the case above

this.instance.doc.getAllMarks().forEach(marker => marker.clear());
护你周全 2025-01-04 20:31:25
//for marking a text and storing it
var cursor = this.instance.getSearchCursor(val);
var scopedInstance = this;

while (cursor.findNext()) 
{
    this.histMarks.push(scopedInstance.instance.markText(cursor.from(), cursor.to(), { className: 'highlight' }));
}


//for removing a marked text by specific intention
for (var i = 0;i < this.histMarks.length;i++)
{
  for (var j = 0;j < this.histMarks[i].lines.length;j++)
  {
    if(this.histMarks[i].lines[j].text.includes(val))
    {
      this.histMarks[i].clear();
      this.histMarks.splice(i, 1);
    }
  }
}
//for marking a text and storing it
var cursor = this.instance.getSearchCursor(val);
var scopedInstance = this;

while (cursor.findNext()) 
{
    this.histMarks.push(scopedInstance.instance.markText(cursor.from(), cursor.to(), { className: 'highlight' }));
}


//for removing a marked text by specific intention
for (var i = 0;i < this.histMarks.length;i++)
{
  for (var j = 0;j < this.histMarks[i].lines.length;j++)
  {
    if(this.histMarks[i].lines[j].text.includes(val))
    {
      this.histMarks[i].clear();
      this.histMarks.splice(i, 1);
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文