13 Apr 2011, 01:05

HTML5 websockets

AKA: The Death Of Polling

Imagine for a moment if you will, a scenario where you have a page on a website that you’d like to update on a regular basis with new content as it becomes available. How would you go about implementing that? Until just recently, you didn’t have a lot of options. You could spin up some Javascript that would do a little setTimeout() magic with some ajax voodoo to call a webservice to get some new data if it’s there. That’s pretty standard, and at least you’re not refreshing the entire page (think meta refresh), right? But, you’re making a lot of consistent, unnecessary calls that may or may not ultimately provide anything valuable. That’s a lot of extra server and network overhead for nothing.

There’s got to be a better way! Enter HTML5!

Part of the HTML5 spec has support for a new technology called websockets.  Just what are websockets?  A websocket is basically a TCP connection for the web, enabling the browser to hold open a connection to a server, and to send and receive messages through that pipe.  What does that mean for us though?

Instead of our setTimeout()/Ajax/webservice cycle, we can simply open a websocket, and wait for our data to show up for us.

Pretending that you’ve installed the Websockets prototype from Microsoft’s HTML5 Labs http://html5labs.interoperabilitybridges.com/prototypes/available-for-download/websockets/html5protos_Download, we can do something like this for a simple echo server:

namespace WebsocketSample {
    using System.ServiceModel;

    public class EchoSvc : WebSocketsService {
        public override void OnMessage(string message) {
            this.SendMessage(message);
        }
    }
}

Pretty trivial there.  Now, how can we use it?

Sprinkle a little markup about, like this:

<input id="input" type="text" /><input id="send" type="button" value="Send" />
<input id="output" type="text" />

And a little Javascript/jQuery action, like so:

var connection = new Websockets("ws://uri/to/EchoSvc");

connection.onopen = function () {
    $('#send').click(function() {
        connection.send($('#input').val());
    });
};

// Log messages from the server
connection.onmessage = function (e) {
    $('#output').val(e.data);
};

And now you have a persistent TCP connection directly from your browser to the server, skipping all of the overhead of the constant polling loop, and multiple server requests.  Muy bueno!

12 Apr 2011, 05:05

HTML5 data-* Attributes

The project that I’m currently working on had a requirement from the User Experience folks to have a button’s text change the first time it was clicked, and then on the second click, the intended action would be performed.  One of the UI design guys on my team suggested adding some new classes that would serve as markers for the text that would be needed.  Something like this:

<input class="switchTo-Buy_Now" type="button">

Technically, yes, that would work.  And then you could bind some jQuery to the click event, parse out the last bit of the class, do some voodoo, and make it go.  But, it’s ugly. 

There’s got to be a better way! Enter HTML 5!

The HTML 5 spec contains support for data-* attributes.  That is, any attribute on any element that starts with data-* is valid HTML 5 syntax, and is used to store data that doesn’t affect the layout, rendering, or function of the elements that it’s attached to.  Finally we can hold any arbitrary data on any element and still have valid syntax!

Further, there’s support for this in jQuery core (as well as vanilla Javascript, but who really cares about that anymore anyway?).

So, we used to have some markup similar to this (which didn’t validate):

<input type="button" class="switchTo-Buy_Now" text="Buy Now!" />

And some jQuery a little something like this:

$("[class$=Buy_Now]").bind('click', function() {
    var class = $(this).attr('class');
    var switchTextId = class.substr(class.lastIndexOf('-')+1, class.length - class.lastIndexOf('-'));
    var switchText = "";
    if (switchTextId == "Buy_Now") {
        switchText = "$4.99";
    }
    // Repeat that a lot.  Or pull it off of some other
    // non-standard attribute.
});

And NOW we have something like this (which is valid to boot!):

<input type="button" class="switchTo" data-switch-text="$4.99" text="Buy Now!" />

and a little jQuery action like this:

$('.buyTo')bind('click', function() {
    var switchText = $(this).data('switch-text');
});

Pretty boss.