Posts about programming

How Much of the Web Actually Work Without Javascript

Recently Paul Boag showed dissatisfaction at the fact that most ecommerce sites don't work without Javascript, which stand against progress enhancement. Coincidentally, I am just now in the middle of working on a Javascript library that aims to make using CSS3 features and writing cross-browser CSS easier. So this got me thinking...

I love Javascript! I won't make any secret of this. I also love writing ajaxy web applications. Although I allow that there's value to making your site work without Javascript, to me, at least, it bares a lower priority. Of course, as is always the case, the answer depends very much on your target audience. Google Docs, for example, is more of a software tool than a web site, and so it wouldn't really make sense to make it work without Javascript - the result probably wouldn't be very useful anyway, because the essence of Google Docs, is the UI.

However, to consider the applicability of my Javascript library, I must consider whether it is acceptable to web designers that their design requires their users to have Javascript enabled.

And so, I resolved to survey how some of the major web sites and web applications look like and work like with Javascript disabled, so as to get a sense of what is the accepted norm on the web today.

The Contenders

I want to survey really popular sites. I also want to survey some content-centric sites, as well as some utility-type web-apps. The list has a Web 2.0 slant to it, but also include some old timers. Without further ado, the list is:

Scoring System

To evaluate how well each site works with Javascript disabled, I will use a scoring metric. The scoring will be based on the following 6 questions, each account for 1 point of the total score. Thus, 6 out of 6 is the perfect score.

  1. Can users navigate the site? (1 point)
  2. Can users read/view the content? (1 point)
  3. Is the site free of broken visual elements? (1 point)
  4. Can users perform the key tasks of the site? (1 point)
  5. Is the site free of broken input elements? (1 point)
  6. If things are broken, are users made aware of it? (1 point)

Let's get started!

The New York Times

Times Screenshot
As expected, the New York Times looked great. Visually it didn't look much different from a Javascript enabled version. Flash ads are replaced by static image ads. One minor hiccup is a twitter widget which appears to spin indefinitely. The video section does not work at all, and there's is no message telling you you need Javascript to run it.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? NO
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? NO(video section)
  6. If things are broken, are users made aware of it? NO(video section)
Score 3/6 for the Times.

Digg

Digg Screenshot
Digg's page looks okay. The flash ads have disappeared, leaving whitespace in their place. You can navigate the site and view articles just fine. However, you cannot "digg" or "bury" articles, which I think is a pretty key task of the site. 
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? NO
  4. Can users perform the key tasks of the site? NO
  5. Is the site free of broken input elements? NO(digg button broken)
  6. If things are broken, are users made aware of it? NO
Digg gets a 2/6.

Facebook

Facebook Screenshot
From a visual stand point, Facebook looks perfect. You can navigate and read most of the content of Facebook, including viewing photo albums. You cannot update your status; you cannot edit your profile; you cannot record videos of yourself, and there's no warning. 
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? NO(can't update status)
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? NO
Facebook's score: 3/6.

Twitter

Twitter Screenshot
Twitter looks great without Javascript, but guess what? You cannot tweet! Bummer. You also can't edit some of the settings in your profile.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? NO
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? NO
3/6 for Twitter.

Stack Overflow

Stack Overflow Screenshot
When you go the SO, a flash banner informs you that the site works best with Javascript enabled: nice, how refreshing! Navigation works, even asking questions, editing and posting works. However, voting does not work. For this one, I'll allow that the key tasks work, because I think the most important things are asking and answering questions; voting, although important, is secondary to those two things.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? YES
5/6. Wow! Way to go, Jeff!

Google Search

Google Screenshot
Google Search works well, however, Image results that come up on the top of the search results show up blank. I gotta say I am very surprised that this doesn't work perfectly. I mean, this is the Google!
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? NO
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? YES
  6. If things are broken, are users made aware of it? NO
4/6 for Google Search.

CNN

CNN Screenshot
CNN worked about as well as the Times. Navigation and reading content worked but not the videos. Although the videos on CNN are more prominent than on the Times, and also break more spectacularly:
CNN Broken Video Screenshot
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? NO
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? NO
3/6 for CNN.

Amazon

Amazon Screenshot
Amazon is the one you gotta count on to do well in this. The site looks perfect. I've tested adding and update the shopping cart, which worked perfectly. I haven't actually gone all the way through and purchased something for this test, but I feel confident that everything would work.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? YES
  6. If things are broken, are users made aware of it? N/A
6/6! Perfect for Amazon!

Ebay

Ebay Screenshot
Ebay is also an old timer ecommerce site. I don't see how it could fail any of these.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? YES
  6. If things are broken, are users made aware of it? N/A
6/6 for Ebay.

Boagworld

BoagWorld Screenshot
Let's see if Paul puts his money where his mouth is. Boagworld looks perfect. forums work. Even the flash videos and audio work! That's pretty amazing. This is the first site I've seen where video works without Javascript.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? YES
  6. If things are broken, are users made aware of it? N/A
6/6. Good On Ya! Paul Boag!

Google Maps

Google Maps Screenshot
Google Maps is the web application that gave life to Ajax. But much to my surprise, it actually works with Javascript turned off. Well... kinda sorta. You can plot an address on the map - even zoom and pan - but you cannot get directions. This is a tough one. On the one hand, it degrades 100% gracefully; on the other hand, without being able to give directions, it's all but crippled. 
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? NO
  5. Is the site free of broken input elements? YES
  6. If things are broken, are users made aware of it? N/A
5/6 for you, Google Maps. Hey, don't be sad, 5/6 is pretty damn good!

Google Docs

Google Docs Screenshot
Ouch! That's not a pretty picture. None of the buttons or sidebar items did anything when clicked. The loading indicators are just stuck there. This thing is pretty much...dead.
  1. Can users navigate the site? NO
  2. Can users read/view the content? NO
  3. Is the site free of broken visual elements? NO
  4. Can users perform the key tasks of the site? NO
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? NO
Wow! Our first - and possible only - 0/6. Congrats Google Docs!

Gmail

Gmail Screenshot
Two epic fails in a row from Google? Are you kidding me? Oh, but wait! What's this? On the bottom right there's a "Load basic HTML" link. You click on it and...
Gmail Screenshot 2
Tada! Talk about drama! That's like a last second Hail-Mary pass for a TD or something. The functionality is all there for the basic HTML version. The only thing I'd pick on is the fact that it's not made very apparent that this option is available. In other words, the degradation ain't so graceful. I guess you could call it clumsy degradation?
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? NO
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? YES
  6. If things are broken, are users made aware of it? NO
4/6 is all you get, Gmail!

Remember The Milk

Milk Screenshot
Well, at least they are up-front about it...
  1. Can users navigate the site? NO
  2. Can users read/view the content? NO
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? NO
  5. Is the site free of broken input elements? YES
  6. If things are broken, are users made aware of it? YES
3/6. Wow, you can not work at all, and still get 3/6!

Flickr

Flickr Screenshot
Flickr looks great, and mostly works. The things that don't work are in-place photo editing features, adding tags and people.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? NO
4/6 for Flickr.

Picasa Web

Picasa Web Screenshot
Picasa Web informs you that your browser is not fully supported, but you are welcome to have a look around. You can see some pictures under the "Explore" tab, but not your own pictures. You also cannot upload your own pictures. It's basically crippled.
  1. Can users navigate the site? NO
  2. Can users read/view the content? NO
  3. Is the site free of broken visual elements? NO
  4. Can users perform the key tasks of the site? NO
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? YES
1/6. Google, Google. Not doing so well, are you?

YouTube

YouTube Screenshot
Hate to rub it in, but YouTube is a FAIL as well. You can still navigate the site, but not play any videos.
  1. Can users navigate the site? YES
  2. Can users read/view the content? NO
  3. Is the site free of broken visual elements? NO
  4. Can users perform the key tasks of the site? NO
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? NO
1/6 for YouTube.

WordPress

Wordpress Screenshot
WordPress works for the most part, but the parts that don't work do not degrade gracefully. Comments are broken. "Visual" editing is also broken, but you can write posts.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? NO
4/6 for Wordpress.

GitHub

GitHub Screenshot
Last but not least, GitHub. I am, after all, the geek's geek. GitHub actually works very well. The only hiccups are small UI elements like the URL box, and the "Add File" button of the Gist dialog.
  1. Can users navigate the site? YES
  2. Can users read/view the content? YES
  3. Is the site free of broken visual elements? YES
  4. Can users perform the key tasks of the site? YES
  5. Is the site free of broken input elements? NO
  6. If things are broken, are users made aware of it? NO
4/6 for GitHub.

Final Tally

Here is a summary of all the scores:
Site vs Score Chart
The winners were Amazon, Ebay, and Boag World. 
The average score for all the sites surveyed is 3.52. Only 26% of the site had a score of 5 or higher. What this practically means is that 74% of the sites had something broken about them when Javascript is disabled.

Summary By Metric

Summary By Metric Chart
What this chart shows is that most sites allow users to navigate and/or view the content on the site, in fact around 80% of them do. But, I think it's important to note that only 58% allowed users to perform the key tasks of the site. In other words, the other 42% are basically crippled. Another thing to note is that only 16% of sites that are broken let their users know that the site is broken without Javascript in some form or fashion - this is actually a really easy thing to fix, one could do what Stack Overflow does and just put up a flash banner on the top of the page, and be done with it. What this shows is that the developers of these sites either didn't tested the site with Javascript off, or just didn't think this was important enough to fix.

See this spreadsheet for all the data in one place.

Conclusion

What have we learned? Well, if you insist on turning off Javascript, the web isn't going to be much fun. It should be noted however that the ecommerce sites (and serious web designers) are the ones that take this very seriously.

As for the Javascript library that I am building: I plan on releasing it soon. I think maybe what I'll do is to let Javascript-enabled be the default mode of operation, but given a fallback option, albeit somewhat more complexed one.
Posted by Toby about 21 hours ago about javascript, programming, tech and webdesign (0 comments)

Javascript sort() Gotcha

Javascript pop quiz!

What is the result of this code?
var arr = [12, 3, 24]
arr.sort()
arr
You: [3, 12, 24]
Me: Wrong, You get an F! The correct answer is: [12, 24, 3].
You: WTF?
Me: Array.prototype.sort() uses lexical ordering by default. That is to say, it converts everything to string before comparing them. Thus, '12' comes before '24' comes before '3'.
You: So how do you make it sort numbers?
Me: You pass it a comparator function as an argument:
arr.sort(function(a, b){
  return a - b
})
You: That makes sense, I guess. But still...that is pretty messed up.


Posted by Toby 7 days ago about javascript and programming (0 comments)

Memoize for Javascript

I wrote a memoize function for Javascript today to cache file timestamps. I thought I would share it with the world. Here is the code:
function memoize(f){
    var cache = {}
    return function(){
        var keys = []
        for (var i = 0; i < arguments.length; i++){
            keys.push(typeof(arguments[i]) + ':' + String(arguments[i]))
        }
        var key = keys.join('/')
        if (key in cache){
            return cache[key]   
        }else{
            var val = f.apply(null, arguments)
            cache[key] = val
            return val
        }
    }
}
Let's say you have a function:
function f(x, y){
  return x + y * 2
}
If you memoize it:
f = memoize(f)
The first time you call f with arguments (3, 4):
f(3, 4) => 11
It will compute it, but the second time:
f(3, 4) => 11
It will merely return the cached value computed from the last time.

Note about the implementation: the equality metric used by this memoize function is: 2 objects are equal iff they are of the same type:
typeof(one) == typeof(other)
and, they have the same string represention:
String(one) == String(other)
That is it. Enjoy!
Posted by Toby 7 days ago about javascript and programming (0 comments)

Flex Compiler Slower on 64bit Mode Java on Snow Leopard

Ever since I upgraded to Snow Leopard, the my flex apps seemed to compile slower. Today, I finally had enough and took a look into this problem. First, there was the weirdness with Java on Mac in that even though the compiler is a command line application(non-GUI), it creates a application menu. I cracked open the mxmlc script, and added:
-Djava.awt.headless=true
to VMARGS. This solved that issue, but didn't make it compile much faster.
Then, after a bit of fiddling around, it turned out that putting java into 32bit mode:
-d32
fixed the problem! The difference was significant. I tested this in 2 different apps. For App 1, it took 45 seconds to compile on 64bit mode, only 9 seconds on 32bit mode. For App 2, it took 30 seconds on 64bit mode, only 7 seconds on 32bit mode. So, mxmlc performs 4-5 times slower on 64bit java than 32bit, java. Why would this be the case, I have no idea. If anyone has an idea, I'd love to be enlightened. If you come across this problem, the fix is to open up mxmlc, and edit the line that says:
VMARGS="-Xmx1024m -Dsun.io.useCanonCaches=false"
and change it to:
VMARGS="-Xmx1024m -Dsun.io.useCanonCaches=false -Djava.awt.headless=true -d32"
I hope that helps someone.
Posted by Toby 3 months ago about flex and programming (0 comments)

Taking an Average in CouchDB

More fun with CouchDB, this time taking an average of something:
// map
function(doc){
    emit(null, doc.info.size) // in place of doc.info.size, you'd put whatever
                               // value you want averaged here
}
// reduce
function(keys, values, rereduce) {
    if (!rereduce){
        var length = values.length
        return [sum(values) / length, length]
    }else{
        var length = sum(values.map(function(v){return v[1]}))
        var avg = sum(values.map(function(v){
            return v[0] * (v[1] / length)
            }))
        return [avg, length]
    }
}
The end result will be 2 values, the first is the average, the second is the total number of values that we took an average of. Phew! Who woulda thought taking an average would be so involved!
Posted by Toby 5 months ago about couchdb, javascript and programming (0 comments)

Retrieve The Top N Tags in CouchDB

I am reading up on how map/reduce works in CouchDB, think I am getting the hang of it now, thanks to this great tool. I tried the "Retrieve the top N tags" example on this page. It didn't work for me at all. So I wrote my own as an exercise. Here's my code:
// the map function
function(doc){
    for(var i in doc.tags)
    {
        emit(null, doc.tags[i]);
    }
}

// the reduce function
function(key, values, rereduce){
    var hash = {}
    if (!rereduce){
        for (var i in values){
            var tag = values[i]
            hash[tag] = (hash[tag] || 0) + 1
        }
    }else{
        for (var i in values){
            var topN = values[i]
            for (var i in topN){
                var pair = topN[i]
                var tag = pair[0]
                hash[tag] = (hash[tag] || 0) + pair[1]
            }
        }
    }
    var all = []
    for (var key in hash)
        all.push([key, hash[key]])
    return all.sort(function(one, other){
        return other[1] - one[1]
    }).slice(0, 3)
}
The approach I took was different one from the one from the example page, but I believe it to be the more correct one: rather than returning the results keyed by the tag in the map step, I would emit every occurrence of every tag instead. Then in the reduce step, I would calculate the aggregation values grouped by tag using a hash, transform it into an array, sort it, and choose the top 3. For the rereduce case, I would combine a set of top 3 choices and then again pick the top 3 among them.
Posted by Toby 5 months ago about couchdb, javascript and programming (0 comments)

Adding Real Properties to FABridge

Although FABridge is a nice tool, it's got its shortcomings. I am going to fix one of them now, namely that it doesn't give you real properties, but uses Java's getter setter convention instead. In 3 out 4 browsers, the __defineSetter__ and __defineGetter__ methods are already usable, so why not take advantage? It's really easy as it turned out. Change the addPropertyToType method to:
    addPropertyToType: function(ty, propName)
    {
        var c = propName.charAt(0);
        var setterName;
        var getterName;
        if(c >= "a" && c <= "z")
        {
            getterName = "get" + c.toUpperCase() + propName.substr(1);
            setterName = "set" + c.toUpperCase() + propName.substr(1);
        }
        else
        {
            getterName = "get" + propName;
            setterName = "set" + propName;
        }
        function setter(val)
        {
            this.bridge.setPropertyInAS(this.fb_instance_id, propName, val);
        }
        ty[setterName] = setter;
        function getter()
        {
            return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName));
        }
        ty[getterName] = getter;
        if (ty.__defineGetter__)
            ty.__defineGetter__(propName, getter);
        if (ty.__defineSetter__)
            ty.__defineSetter__(propName, setter);
    },
 And..., voila! You got yourself real properties. Now instead of writing:
app.getTextBox()
You will be much happier writting:
app.textBox
On non-sucky browsers that is.
Posted by Toby 5 months ago about flex, javascript and programming (0 comments)

Typed Deserialization with JSON

JSON is nice, but if you use it extensively, you go against the OO style of object modeling, which says that behaviors should be attached to objects themselves. Even if you are not an OO bigot, the OO way is sometimes just far more convenient and structures your code better, IMHO. Given my past work with JYaml, it can't be that hard to read in some JSON and directly deserialize it into a typed object can it?

Say you have a Person type:
function Person(name){
    this.name = name
}
Person.prototype.sayHi = function(){
    return "Hi! I am " + this.name
}
You create an instance called tommy:
> tommy = new Person('Tommy')
> tommy.sayHi()
Hi! I am Tommy
With a little magic from a toJson function that I whipped up:
> tommyJson = toJson(tommy)
> tommyJson
{__proto__: Person.prototype, name: "Tommy"}
tommyJson is now a string representation of tommy. You can see that it sets the special __proto__ link to Person.prototype, which will do its magic when it's deserialized. Now let's deserialize it back:
> tommyCopy = fromJson(tommyJson)
> tommyCopy.sayHi()
Hi! I am Tommy
> tommyCopy.constructor
function Person(name){
    this.name = name;
}
> tommyCopy === tommy
false
As you can see, the deserialized object tommyCopy is not just a plain object literal, but has all of the behaviors of Person.

The code for toJson and fromJson is so small I don't even bother putting it on github, so I'll just post it here(You may need ecma5array if you want to run it on a sucky browser):
function toJson(obj){
    function keys(o){
        var ret = []
        for (var key in o){
            var val = o[key]
            if (o.hasOwnProperty(key)) // exclude attributes in the parent
                ret.push(key)
        }
        return ret
    }
    function quote(str){
        return '"' + str + '"'
    }
    if (obj === null || obj === undefined)
        return String(obj)
    else if (obj.constructor === String)
        return quote(obj)
    else if (obj.constructor === Array)
        return '[' + obj.map(toJson).join(', ') + ']'
    else if (obj.constructor === Object)
        return '{' + keys(obj).map(function(key){return key + ': ' + toJson(obj[key])}).join(', ') + '}'
    else if (obj.constructor && obj.constructor.name)
        return '{' + ['__proto__: ' + obj.constructor.name + '.prototype'].concat(
            keys(obj).map(function(key){return key + ': ' + toJson(obj[key])})).join(', ') + '}'
    else
        return String(obj)
}
function fromJson(str){
    return eval('(' + str + ')')
}

Posted by Toby 5 months ago about javascript, programming and prototype (0 comments)

Vector for ActionScript3

I just learned about Vector, it's a typed Array for Actionscript 3, like generics in Java or C#. However, in Actionscript 3, Vector is a one-off: it's the only class that uses the generics syntax, and developers cannot use generics in their own classes. Nevertheless, Vector gives a type-safe alternative to Array and promises big performance gains. Given that it can also give the type of the containing elements at runtime, I can use it now to drive JSON deserialization into objects too.
Posted by Toby 5 months ago about actionscript, flex and programming (0 comments)

Google Chrome Frame to the Rescue!

Bruce Eckel's prediction came true! Chrome is now an IE plugin! There's a lot of talk about it at the moment about security concerns and accessibility, but both of these discussions miss the point. The real story here, is what Google Chrome Frame means for developers. Web developers like me have longed for the following:
  • CSS 3 support
  • Canvas
  • SVG
  • Properties and other advanced features in Javascript
  • HTML 5
  • Not having to develop for a browser that sucks
Now, rather than resorting to campaigns like these, you can instead ask your users to install a plugin - much like with the Flash plugin - that will essentially run Chrome's engine inside IE 6, 7, or 8, and give you all of the benefits in the list above. The average end-user will hardly notice the difference because IE's interface will stay the same, the only things that are different are within the content pane of the browser. Given Flash's ubiquity with its browser plugin install model, it is certainly not unconceivable for Chrome Frame to become wide spread among IE users. Go back a few years: How did Flash gain this level of penetration in the first place? Answer: YouTube! Who owns YouTube now? Oops! Yes, Google could totally drop Flash from YouTube and go HTML 5 only. I doubt they would do that in reality, but that card is there for them, if they want to play it. The more probable Google strategy will be Wave, which, I gather from Google's positioning, will definitely not support IE natively. So, if Wave hits a home run and becomes the next big thing, Chrome Frame - and thus HTML 5 - will become a very viable RIA environment. Heck, some other company could very well come into the picture at this point and develop a killer app in HTML 5 that pushes it over the top also. When we get to that point - and here's me praying - it's bye bye to developing for the IE platform, forever!


Posted by Toby 5 months ago about programming, tech and web (1 comments)

HTTP Server in 5 Lines With Webrick

Usually when I am prototyping a web UI - either in Javascript or Flex, I would just write a static html, because that's the simplest thing that works. But, once in a while, it doesn't work because of the security restrictions that the browser imposes on local files. Maybe you want to use ajax calls(which is sometimes problematic on IE), trying to use the google maps api, or the FABridge, whatever the reason may be. Well, you can get around this problem easily using this ruby script:
require 'webrick'
server = WEBrick::HTTPServer.new :Port => 1234
server.mount "/", WEBrick::HTTPServlet::FileHandler, './'
trap('INT') { server.stop }
server.start
This runs a web server at http://localhost:1234/ which mounts the top level directory to your current directory.

Update: Oops, it's not exactly that easy after all. In order to prevent caching - which you will want to do if you are doing development - you will want to write an extra class. The modified script:
require 'webrick'
class NonCachingFileHandler < WEBrick::HTTPServlet::FileHandler
  def prevent_caching(res)
    res['ETag']          = nil
    res['Last-Modified'] = Time.now + 100**4
    res['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
    res['Pragma']        = 'no-cache'
    res['Expires']       = Time.now - 100**4
  end
  
  def do_GET(req, res)
    super
    prevent_caching(res)
  end

end

server = WEBrick::HTTPServer.new :Port => 1234
server.mount "/", NonCachingFileHandler , './'
trap('INT') { server.stop }
server.start
Not 5 lines anymore, bummer! The code for NonCachingFileHandler was stolen  from unittest_js.
Posted by Toby 5 months ago about html, javascript, programming and ruby (0 comments)

I Learned Something About Scala

I am trying to learn Scala. Here's me trying. Don't forget to look for my write up at the end where I answer my own question.
Posted by Toby 7 months ago about haskell, programming and scala (0 comments)