Scraps of JavaScript
By Simon HarrisNot much today but some little bits-and-pieces of stuff I’ve picked up over the last two weeks. It’s been a steep learning curve going from no JavaScript to writing a character-based terminal emulator and it’s sure been fun.
Now that I have a modicum of JavaScript under my belt, I think I’ll finally take Big Daz’ advice and have another look at prototype. I had a quick look initially – on his recommendation – but I was so new to the language that none of it made much sense. FWIW, thanks again to Big Daz, I also spent a lot of time reading quirksmode.org.
Overall, DHTML works really well. The browsers seem to handle running JavaScript pretty well – the performance is quite impressive – and it’s not that difficult to get things to work cross-browser.
So, here we go…
Rather than report an error, most browsers seem to silently fail or at best give a rather less than helpful message – either by way of a pop-up or a message to the JavaScript console.
The error messages in Mozilla – sent to the JavaScript Console – are far more useful than those generated by Safari – also sent to the JavaScript Console; MSIE is woeful when reporting (by way of a pop-up) errors in JavaScript files that have been included via <script language="javascript" src="..." type="text/javascript" />.
The debugger for Mozilla works a treat.
Methods can’t be named the same as fields – they’re really just the same thing anyway. Not really a problem but I was translating some code to JavaScript and it didn’t work out as I had planned ;-). Either use an underscore (_) for field names; make sure your method names are always prefixed with a verb such as get/is/etc.; or “allow” direct access to fields. I say “allow” because strictly speaking, it seems that field values are pretty much always accessible anyway.
Closures usually require that you define a variable with a value of this to ensure you can always refer back to the object that owns the function being called:
var **self** = this;orders.each(function(order) {**self**.process(order);});
To ensure your onkeypress event handler is called with an event object, use something like the following to capture the event and then delegate:
var self = this;document.onkeypress = function(event) {return self.onkeypress(**event ? event : window.event**);}
To have a keystroke ignored seems to require the following code in your onkeypress event:
event.cancelBubble = true;event.returnValue = false;return false;
This works for most everything with the noteable exception of F1 in MSIE which displays help on the browser. To prevent this, try:
document.onhelp = function() {return false;};
The Mac generates very odd key `s for things such as Up (63232), Down (63233), Left (63234), Right (63235), etc. I say odd only because I’m used to the ones generated on PCs (38, 40, 37, 39, …). Ok, so maybe they’re not odd just different ;-)
MSIE seems only to allow you to modify the content (DHTML) of a div.
Even though the HTTP protocol allows you to send and receive binary data – using Content-Type: application/octet-stream and Content-Transfer-Encoding: binary for example — none of the browsers I tested would reliably allow the JavaScript code to receive that data as a string of characters, even though the browser would quite happily download the content to a file on my hard-disk and allow me to manually construct a string with identical content – using String.fromCharCode(0x1b) for example.
You can simulate Swings invokeLater by using window.setTimeout() with a time-out value of zero:
var self = this;window.setTimeout(function() {self.doSomething(...);}, **0**);
Most of the browsers I tested didn’t seem to support for .. **in** ..; they all accepted the syntax but produced kooky results when used.
All browsers I tested support using innerHTML to replace the content:
document.getElementById(id).innerHTML = html;
Using a span with CSS classes is the simplest way to inline style changes:
<span class="important">...</span>
Handling errors (and for that matter state changes) when using XMLHttpRequest (or in the case of MSIE, ActiveXObject("Microsoft.XMLHTTP")) differs between browsers:
- Safari and MSIE seem to always set
request.statusandrequest.statusText; - Netscape/Mozilla seem to sometimes set these variables, yet other times throw exceptions due to the varible having not been defined;
- Most will allow any old value for request method and URL and notify you via
onreadystatechangeif there was an error – such as 404 Not Found for example – though sometimes (under what circumstances I don’t recall) they will throw an exception onopen()and sometimes onsend().
Both Netscape/Mozilla and MSIE append a CRLF (0x0d0a) to the end of any content you send, leaving the Content-Length field two-bytes short; Safari seems to leave the content as-is. Not really a problem but interesting as the data already had the CRLF as usually recommended for sending content via HTTP.
To change the colour of a horizontal-rule (<hr class="a_style" />) in a browser-neutral manner, you need to set your CSS style as:
hr.a_style {background-color: #NNNNNN;color: #MMMMMM;border: 0;height: 1px;}
You can call a method using a string for the name, allow a switch-like calling mechanism:
var methodName = (this.insertMode) ? "insert" : "overwrite";**this[methodName]**(aCharacter);
More to come I’m sure. Add any more you can think of or let me know of better ways to do these things as I’m truly ignorant in this space.