CodeMirror

This is part 7 of my series on developing with only an iPad. Part 1

Once I had my code editor working with a standard text area, replacing it with CodeMirror was pretty easy, and it works surprisingly well on the iPad.

Unlike the standard text area, it doesn’t try to select the start/end of a word. I wasn’t sure that would be enough, but after using it for a bit I think I don’t need to add arrow keys after all.

Naturally, there are a couple of things that need improving on to make it usable though, the main ones being that selection doesn’t work, and not being an actual text area it doesn’t get access to the clipboard.

Scrolling

When the on screen keyboard is shown, iOS is sometimes a little too smart about making sure the active input visible, and most of the toolbar buttons disappear as soon as you touch the code. While not something that would stop me getting work done, it did get severely annoying.

I actually needed to modify some CodeMirror internals for this one, but the CodeMirror code turned out to be fairly easy to follow.

Since the visible code editor, doesn’t correspond directly to the textarea iOS sees, I was able to keep the textarea at the top of the screen to stop the scrolling.

d.inputDiv = elt("div", [input], null, "overflow: hidden; position: absolute; top: 0 !important; width: 3px; height: 0px;");

Hopefully this will work out as a proper fix as well as a quick hack and make it into the codebase.

Fixing selection

It would probably be possible to set up touch events properly and get something like native selection working, but I went for the quick hack - add a button that puts the app into selection mode so at the next tap selects from the current cursor.

view.selectMode = !view.selectMode;
cm.setExtending(view.selectMode);

It’s a little bit clunky, but easy to implement and a lot better than nothing.

Working around clipboard restrictions

Working in the browser you basically have two choices - use a standard text area or not get access to the clipboard. A hybrid approach with a hidden text area sort of works, but adds a lot of limitations and runs into other issues like the unwanted scrolling above.

My solution is a two step process - paste into a standard textbox, then script can copy that into the code editor. This step can be bypassed if you just want to copy and paste within the app, which covers a lot of the usage.

This is pretty ugly, but I see the proper solution as bundling with phonegap so that the restrictions just go away. All I need is something that works well enough while it is more important to be able to use a simple page refresh to update the code.

Custom Keys

Adding custom keys to solve the last flow issue with not having a real keyboard turns out to be pretty easy:

$(".keys li", this.element).on("tap click", function() {
var btn = $(this);
var k = btn.attr("data-key");
cm.focus();
cm.replaceSelection(k);
cm.setCursor(cm.getCursor("end"));
return false;
});

Further refinement

There are a few other things I can probably improve on - for example scroll events working differently on iOS messes with the rendering a bit. However, with the more significant issues above fixed, it is definitely a workable solution.