Wednesday 23 December 2009

DOM key event confusion

There are two standard sets of events that can be used to detect key presses, the first is onkeypress and the second is both onkeyup and onkeydown. Initially I went with onkeypress for my terminal, just to keep it simple.

When you are wanting to receive presses of what are called special keys, using onkeypress becomes a problem. In Firefox you can intercept the pressing of the backspace key, but in Internet Explorer this event never receives it and instead the browser goes back to the previously viewed page. Other keys that onkeypress does not handle in IE, include the cursor keys.

In order to work around this, I switched to onkeyup and onkeydown. Now all key presses, normal or special, work perfectly well in both browsers. However, there is another problem. All keys received are upper case characters, and various keys on the keyboard give symbols rather than their expected characters. The ',' key for instance gives the '¼' character.

Typing the following:

This is a test..,,,.M,,,,
Gives the following output:
THIS IS A TEST¾¾¼¼¼¾M¼¼¼¼
I made countless web searches trying to work out why this was. I even tried manually searching around Stack Overflow. I found web pages where someone was asking how to make the character received from onkeydown upper case, which implied that the problem was on my end. I was pretty much resigned to the existing behaviour, and was planning to use onkeypress to get the entered characters and onkeydown/onkeyup to get the special key presses. However it seemed like a hack, to work around the fact I didn't know what the problem was.

A last ditch question in ##javascript on the FreeNode IRC server yielded the following information:
[16:59] <deltab> chglpnts: keydown and keyup are lower-level, just identifying which *keys* have been pressed; keypress comes later, after the specific combination of keys has been converted into a character
[17:00] <chglpnts> deltab: Ah, I wondered if that was the case, but could find no references. How do I convert for instance 1/4 into , or is the standard way to use keydown/keyup for special keys but still use keypress for normal ones?
[17:00] <deltab> chglpnts: use both
I wonder where this this difference is clearly stated. Searching w3.org for onkeydown does not yield any relevant pages. It is stated in the Detecting keystrokes article on the quirksmode web site, although I was unable to distinguish the meaning until I was already aware of it.

In any case, I am now back on track..

CSS attribute matching and browsers

The goal is to have a blinking cursor. One approach I tried out, was through the use of attribute selectors, where making the cursor visible or not would be a matter of changing an attribute value.

Here's the HTML element:

<font id="cursor" class="cursor" shown="yes">
And the javascript to change the custom "shown" attribute:
if (cursorElement.getAttribute("shown") == "yes")
cursorElement.setAttribute("shown", "no")
else
cursorElement.setAttribute("shown", "yes")
With the following style sheet entries:
.cursor[shown="yes"] {
color: #7799CC;
background-color: rgb(241,128,22);
}

.cursor[shown="no"] {
color: white;
background-color: #7799CC;
}
This works perfectly in Firefox 3.5.6, but Internet Explorer 8.0 completely refuses to recognise the custom attribute. I'm not sure if there is a way in which this can be made to work in IE without defining custom DTD entries, but for now, I've gone back to an approach where I change the element class to make it blink.

Sunday 20 December 2009

A step towards a Comet-based terminal

While I already have a rough and dirty web page that allows text to be entered, sent to the server and then echoed to anyone viewing the page, it isn't really inspiring enough to take any further. It's overly complicated and hacked together by an advanced manner of cut and pasting, from a selection of code found somewhere on the internet. In order to proceed with any project based on the functionality it is supposed to provide, I need a clean replacement for it.

Motivation

Code does not write itself. Although it was raining today, I needed to find a hook to get myself interested in this project. So, in order to motivate myself to implement a replacement from scratch, I took my inspiration from the AmigaDOS shell.


A thing of marvel, my goal was to get something that looked and appeared to work as close to it as possible.

Challenges

I had a little trouble getting the text to wrap right. Whenever a word which was longer than the width of the window was entered, the text entry continued off unseen outside the right of the window, resulting in the addition of a horizontal scrollbar. With a little CSS research, this was fixed by adding the following two lines:

  word-wrap:   break-word;
overflow-y: scroll;
There is, I have just noticed, one remaining bug. Because the console text is directly manipulated HTML, consecutive spaces are not displayed. I need to add the following:
  white-space:  pre-wrap
And finally, when you've entered enough lines to bring the vertical scrollbar into play, it doesn't automatically scroll. I still need to look into that.

Result

Eventually, I had to decide whether I was going to concentrate on functionality or the detail of its appearance, and functionality was the obvious winner. In its current state, the terminal supports the following:
  • Dragging the "window".
  • Text entry.
  • Movement of the cursor within the current line being entered.
  • The enter key starting a new line.
  • The backspace key removing the character before the cursor.
  • The del key removing the character under the cursor.
You can try it here.. although at this stage, it has only been tested in Firefox 3.5.5.