javascriptcodemirrorcodemirror-modesui-codemirror

Dynamic line counts in Codemirror gutter is empty every second time the key is pressed


I was tasked to build a note input area where i should show line count and character count in each line. I chose codemirror to do it. Everything works but the Line character count seems to be blanking out every second key press. I have attached video link to the issue and the code is pasted below. Thank you

Video of issue

var count;
var textEditor = CodeMirror(document.getElementById('noteArea'), {
  lineNumbers: true,
  autofocus: true,
  gutters: ["CodeMirror-linenumbers", "lineLength"],
  lineWrapping: true
});

textEditor.on("cursorActivity", function(cm, change) {
  var doc = cm.getDoc();
  var cursor = doc.getCursor();
  count = 50 - cursor.ch
  var line = cursor.line
  var info = cm.lineInfo(line);
  cm.setGutterMarker(line, "lineLength", info.gutterMarkers ? null : makeMarker());

  function makeMarker() {
    var marker = document.createElement("div");
    marker.style.color = countColor(count);
    marker.innerHTML = count || "●";
    return marker;
  }

  function countColor(count){
    if (count < 0 ) {
      return "#822"
    } else {
      return "green"
    }
  }

  // var line = doc.getLine(cursor.line);
})

Solution

  • The bug is this line:

    cm.setGutterMarker(line, "lineLength", info.gutterMarkers ? null : makeMarker());
    

    Solution:

    If you want the marker to always be the result of makeMarker(), just remove the ternary:

    cm.setGutterMarker(line, "lineLength", makeMarker());
    

    Explanation:

    What the original line does is:

    Since info.gutterMarkers is the marker for the current line (that is, it's modified every time you call setGutterMarker), that line is toggling between the two cases (first the marker is falsy, so it sets it to <div>50</div>, then the marker is truthy, so it sets it to null, then the marker is falsy, so it sets it to <div>48</div>...). That's what causes the alternating behavior you observed–the gutter marker is set to null every second press.