javascriptcodemirrorcodemirror-modes

Codemirror v5 Dynamically Add Multiple Cursors


I'm using Codemirror v5.65.12. I know I can press and hold the CTRL key and then click to add multiple cursors into the editor. However mobile users don't have a CTRL key. My first attempt was using...

EventTarget.dispatchEvent() to trigger the ctrlKey to be down as long as a class is visible. I had no success with this attempt.

I'm also aware that Codemirror comes with an undocumented function triggerOnKeyDown with which you can trigger a keydown on Codemirror.

const ev = {
  type: 'keydown',
  keyCode: 13 // keycode for the Enter key, use any keycode here
};
cm.triggerOnKeyDown(ev);

However when I tried that using ctrlKey alongside onclick on the editor I wasn't able to successfully add multiple cursors for mobile in Codemirror.

I'm aware I can use .getCursor() to get the cursor's position and I can use .setCursor() to set the cursor's position but no matter what way I approach this I always manage to just move the cursor position to a new position instead of adding an additional cursor when I touch on mobile (specifically Android).

Is there a way in Codemirror v5.65.12 to dynamically add multiple cursors to a Codemirror instance that doesn't require a desktop (IE holding down the ctrlKey)? If not what other methods can I do to achieve this?

Codemirror .getCursor()


Solution

  • Looking at the code it does not look at the key events but instead looks for the modifier keys event.ctrl (and ev.metaKey on MacOS) in the mouse event:

    https://github.com/codemirror/codemirror5/blob/658bff7c56b7829aeabb8a914be5ca728d8aba0b/src/edit/mouse_events.js#L124

    There we can also see that we can overwrite behaviour via configureMouse, which will add a new cursor when we return {addNew:true} (for more info search for configureMouse on https://codemirror.net/5/doc/manual.html#config)

    var multiselectCheckbox = document.querySelector("#multi");
    var editor = CodeMirror.fromTextArea(document.querySelector("#code"), {
      lineNumbers: true,
      configureMouse: (cm, repeat, ev) => {
        if (multiselectCheckbox.checked) {
          return {
            addNew: true
          }
        } else {
          return {}
        }
      }
    });
    <link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.12/codemirror.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.12/codemirror.min.js"></script>
    
    <label for="multi">Create more cursors</label>
    <input type="checkbox" id="multi" />
    <textarea id="code" name="code">
    // some sample source code
    CodeMirror.fromTextArea(document.querySelector("#code"), {
        lineNumbers: true,
        configureMouse: (cm, repeat, ev) => {
          if (multiselectCheckbox.checked){
            return {addNew:true}
          } else {
            return {}
          }
        }
      });
    </textarea>