Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Codemirror 2.2 clear all marks

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 ?

like image 598
ic3 Avatar asked Jan 25 '12 10:01

ic3


1 Answers

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
like image 179
purgatory101 Avatar answered Sep 23 '22 17:09

purgatory101