Carets and tabs

2011-03-12

So the past few weeks I've been very busy with a very cool demo. Although the demo really isn't ready yet, I'd like to share some frustrations I've had creating an editor kind of thing.

The problem is highlighting text in the browser. Seems like an easy thing to do, but turns out to be a pita. There are several ways of doing this, I ended up using the invisible textarea covering the visible html.

The major problem in this approach is the fact that your caret is also hidden. This puts the major burden of showing the caret in your hands. The only caret api that browser expose is the position, relative of the entire content length. Oh and there is no caret event, you can only go by key and mouse events (don't forget about the mouse... ;)). And it turns out that there's a lot of work for that stupid little blinking line. Who knew!

So while the major part of displaying a caret is on a whole not that difficult, there's oooone little caveat that will come to bite you in the ass. His name is tab. And variable length is his game.

It's common knowledge that a tab character in the browser (white-space pre..) is 8 characters wide. For some reason, this is "pretty much" non-configurable. However, this is a max width, not a fixed width. More to the point, the tab stops are at an 8 character interval. Meaning that from any point in the document, a tab causes a space to fill up all the way to the next tabstop from the current position. And this is the problem.

You can't really take the string for a single line and count the number of tabs in it. You'll desync and eventually end up with an incorrect number of characters on that line, if there's a tab that doesn't start at a tabstop. The correct number of characters for a tab is (8-(col%8)). But as you can see, that requires knowing the current col. This basically means that you'll have to start at the start of a line (only there do you know for sure that the col is zero) and count all characters and tabs in order to know the correct width of that tab.

And that's just a major performance hit :(