Node.js

May 22nd, 2010

I just watched Ryan Dahl — Introduction to NodeJS on YUI Theater and I am very exited, it surprised me, it sounds really crazy without the details. Today’s web servers mostly use threads or processes for each request they serve. The problem with this is the fact that threads and processes cost resources(CPU cycles and RAM), this is justified by the fact that most requests start and end very quickly, however if we have a lot of concurrent requests things can really heat up. If a web server gets a lot of incoming requests at the same time it needs to have a lot of threads/processes running, which increase the RAM and CPU usage and decrease the response time. This is a grave problem if we have a high traffic site or a chat application which keeps a connection open for a very long time.

So the question may be asked: why do we use threads anyway?

The answer: We could use a nice event loop but the problem is that we have a lot of function calls that block the execution like this one:

result = db.query(“SELECT * FROM foo”);

This line of code will pause our current thread until we get a answer from the database, and it takes long(socket connections etc.). In an event loop we can’t afford to have these instructions pause our loop, that means that we would basically have our clients wait in line.

The resolution: Make them stop blocking us!

So If we were to turn these blocking routines into non-blocking routines we would live in a better world.

Let’s have a look at JavaScript. The browser is one threaded still we are fine with it, we don’t need no threads there: why is that?

It’s because we have instructions like these:

//do something time consuming
$.getJSON('ajax/some.php', function(data) {
  //wake me up when you are done!
  //do something with the result
});

So we have asynchronous, non-blocking routines in JavaScript, that’s why we don’t care about threads.

If this is better, why aren’t people using this instead of threads?

According to Ryan Dahl, this is mostly because of bad habits, it would be somewhat harder to teach non-blocking IO and basically most of the tools we have now have only blocking IO. I feel that the main reason is probably that most languages don’t make writing callbacks easy and simple, unlike JavaScript.

Solution: let’s write a one threaded web server with JavaScript.

This is what Ryan Dahl and others are doing, this is what Node.js is all about. They abstract the ugliness of the underlying libraries and make IO routines non-blocking.

One may note: JavaScript is not the fastest language…

Answer: V8(Chrome’s JavaScript engine) all the way!

Node.js is far from ready for prime time, but it is definably usable in some cases where we would really need it. I recommend those interested in this to watch the video presentation, and to go to http://nodejs.org/, download Node.js(it’s free, MIT license) and give it a try. I successfully compiled it under Debian unstable and now experimenting with it.

HTML5 Canvas can work even in Internet Explorer 6

May 20th, 2010

The most heard criticism about Canvas is that it’s not supported in IE, and because of that it will only be usable in 12 years. This is certainly not true, I have found a solution that can make a Canvas application work even in IE6, it’s called Explorer Canvas, an Internet Explorer specific implementation of the HTML5 Canvas, and not it’s not a browser plugin, it’s a JavaScript file. We just include excanvas.js like this:

<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->

and let Explorer Canvas do the rest.

This wonderful piece of software was brought to us by Google, and it’s available at http://code.google.com/p/explorercanvas/.

I know this is all nice but: does it really work?

Well I took my very simple graph application and took it for a test run under IE with this included. I got a script error, because fillText is not supported under excanvas, so I took these two lines out and the rest of my code worked, even under IE6:

Now skeptic people may say “HAH, fillText is not supported, this FAILS!”, but the fact is that we could replace these parts, I mean we don’t really need Canvas to draw text most of the time, we can already do that with HTML. So most of the time we could live with this limitation and have a pixel perfect rendering!

There are other things that are not (yet) supported by excanvas, but most of the features are! So I encourage people doing charts to try to use this instead of a flash based solution.

I also made a downloadable package of the experiment I showed earlier, but the excanvas package contains cooler demos. Looking forward to doing more advanced things in the future with all this.

How to write a CKEditor image uploader

May 18th, 2010

CKEditor is an awesome piece of software, it’s essential for good CMS-es that require WYSIWYG editing, the problem however that it doesn’t have an image uploader by default and it’s not a trivial task to write one because it’s documentation is not very good at this part. I spent a lot of time googling for hints on how can I write a PHP backend for image uploads, luckily after some hard work I managed to gather enough info to create a working image upload backend.

1. I have an ajax directory relative to the sites root, I will create an upload.php in this folder.

2. I edit the config.js (inside CKEditor’s directory) and append the following line:

//this needs to be inside: CKEDITOR.editorConfig = function( config )
config.filebrowserImageUploadUrl = 'ajax/upload.php?type=Images';

3. This upload.php will have to deal with a HTTP Post Request of course and the file will be sent from an input named “upload”, in PHP this means that we have to deal with $_FILES['upload']. Also we need to respond to CKEditor which is a little tricky, it involves ad-hoc JavaScripting(which was badly documented when I did this the first time). The following template solves the CKEditor specific issues:

<?php
//process $_FILES['upload']
//store uploaded images URL in $uploadedImageURL
?>
<script type="text/javascript">
window.parent.CKEDITOR.tools.callFunction( <?php echo $_GET['CKEditorFuncNum']?>, '<?php echo "$uploadedImageURL"?>' );
</script>

We normally want to resize the image at this point and tell CKEditor the URL of our resized image. This ad-hoc method is mainly for security.

There is also the option for using CKFinder for file uploads, but I prefer doing custom solutions so that I can have maximum control over my file uploads.

Common jQuery checkbox operations

May 18th, 2010

Tell the checked state for a single element.

var ischecked = $('#foo').is(':checked');

note: using attr instead of this doesn’t seem to work.

Checking the states of multiply checkboxes with selectors.

$("input[type=checkbox][checked]").each(
  function() {
   // Insert code here
  }
);

Check an element.

$('#foo').attr('checked',true);

Uncheck an element.

$('#foo').attr('checked',false);

Pure CSS3 Spiderman Cartoon w/ jQuery and HTML5 – Look Ma, No Flash!

May 17th, 2010

Last week I came across a very nice demonstration of what the HTML5 stack can do with just CSS(3 to be exact) and some minor JavaScripting.

http://www.optimum7.com/internet-marketing/web-development/pure-css3-spiderman-ipad-cartoon-jquery-html5-no-flash.html

The article describes how the animation was created what problems did it required solving and how could the DOM be used for gaining and advantage.

A commentator replied to this article with a blunt suggestion that “This works in 6% of browsers and spikes CPU usage.” and goes on suggesting that this is not usable because it is not supported everywhere. Well it misses the point because this was a well performed experiment.

The browser vendors will have to give sooner or later, we can’t live with IE6 supported technologies forever.

AJAX and linking

May 4th, 2010

Having a HTML fall-back for an AJAX application is good, but sometimes we still need the benefits of having links. If we want our application to have bookmark-able and/or copy-paste-able states and support the back button we need to put a little extra effort into it.

If the location changes in the address bar, the page reloads, this is unacceptable if we have an AJAX application, but luckily this doesn’t apply to the hash(#) part of the URL. If we change only the hash, the page won’t reload, so generally we can store states inside the hash. To do this it’s possible to use them in HTML with links like <a href=”#foo”> or via JavaScript like “location.hash = ‘foo’;”.

Since it’s easy to store states in the URL, all we need is a way to be notified if the state changes. In HTML5 we have an event for this which is good, in older browsers we don’t have this, which is bad, but luckily there is already a jQuery plugin that takes care of this: It’s Ben Alman’s hashchange plugin.

This plugin is really simple to use for coders already familiar with jQuery, it simply provides an event. Here is an example usage for this:

$(function(){
    // Bind the event.
    $(window).bind( 'hashchange', function(){
        // Alerts every time the hash changes!
        alert( location.hash );
    })
});

This is good, but we still need to get some information out of the hash, for this I made a very simple protocol, the main goal is to be able to call functions and pass parameters:

- the hash is made up by parts

- parts are separated by ‘/’

- the first part is the function we want to call

- the parts after the first one get passed as parameters

For example: #foo/1/2 would call foo(1,2)

To make this safer I create an object where I store the actions I want to be mapped, so here is the code I use:

$(function(){
    //a map of our actions
    var actions = {
        foo:function() {
            alert('foo');
        },
        bar:function(a) {
            alert(a);
        }
    }
 
    //parse the hash and decide what to do
    var actionSwitch = function(){
        var action;
        var h = location.hash;
        h = h.split('#');
        h = h[h.length-1];
        h = h.split('/');
        action = h[0];
        h.splice(0, 1);
        if (actions.hasOwnProperty([action])) {
            actions[action].apply(this, h);
        }
    };
 
    //bind our action switch to the hashchange event
    $(window).bind( 'hashchange' , actionSwitch );
 
    //execude the action switch at start too
    actionSwitch();
});

Of course the actions object should contain real actions. The purpose is to have set of mapped functions that we want to call when the hash changes.

Using a system like this also makes tings a lot clearer and makes our application take advantage of the browsers navigation buttons.

Graceful degradation

May 2nd, 2010

I started an interesting project that would become part of my diploma work. I want to create a web gallery(I know, there are zillions out there). It would have a fair amount of features, but it would always degrade gracefully if the browser doesn’t support them.

Sounds easy, but the stipulation is that my code(does not include libraries that I use) must not look at neither browser names nor version strings. I consider user agent string sniffing to be both evil  and idiotic.  I think that feature detection is far superior to user agent sniffing and it’s a lot easier too, I fail to understand why people used user agent string sniffing in the first place, when they had feature detection all along. This is a very good article on user agent sniffing, it illustrates why it’s bad: http://webaim.org/blog/user-agent-string-history/

GMail used user agent sniffing in the past(don’t know if they use it today). Yahoo uses user agent sniffing currently. Again I can’t understand why are they doing it, and if they are doing it why are they so lazy. I try to view Yahoo Mail in the hottest version of Chrome under Debian, with Adobe Flash installed and I get this:

It’s close, but no cigar. This really puzzles me, the Yahoo developers should be aware of feature detection, they talk about it…

I want to do better, I want to demonstrate that it’s possible to create web apps that get the most out of all browsers. The first step is to create ridiculously oversimplified version of the application by only using standard HTML and minimal CSS. This would work on all browsers, so far so good. The next step would be to put some JavaScript that could transform our minimal application on runtime. This layer would fully ajaxify the whole application, it should work on all browsers that support jQuery and jQuery UI. There are some really new HTML5 features out there, browser vendors spent a lot of work in to them, it would be a shame to not make use of them. This is where the real feature detection comes in, luckily it is very easy to detect HTML5 feature, it works simple JavaScript feature detection style.

End of story? Well not really. A friend of mine showed me a HTML5 Geolocation demo, and asked me to try it on my Android 1.6 based phone. It didn’t work, I was shocked. My phone has a GPS built into it and I use various GPS tracking software with it, it must have Geolocation. Surely the demo is wrong. Well no, the demo was right, my phone didn’t support the HTML5 Geolocation but instead it had the Google Gears Geolocation, which is good enough. With some tweaking I made the Geolocation demo work with my phone too, the HTML and Gears implementation are almost interchangeable, there are minor differences, probably because Gears is no longer developed, but it takes little effort to make a script work with both of them.

Another interesting layer would be to add mobile support to a page, but I don’t really know how could that be accomplished without user agent sniffing, I am experimenting in this area though.

My current progress shows that it’s not all that hard to make an application that can work without JavaScript, than transforming it with JavaScript to a better application. I hope I will have time to add all my planned features to this application.

How to hack jQuery widgets

May 2nd, 2010

The first thing we need to do is create an inline anonymous function that sandboxes our hack

(function($) {
       //code here
})(jQuery);

This way we ensure that our global variables will be only visible by us and that our hack will work even when the $ is not the jQuery object.

In the next demonstration we will give the jQuery dialog a new fixedcenter option, that would lock the dialog to the center, to do this we will overwrite two methods, the _init and the _setData method, the _init gets called when the dialog gets initialized, and the _setData gets called when an option is set.

(function($) {
    //variable that keeps fixedcenter elements 
    var fcDialogs = [];
    //an event handler, that is called when we need to center the dialog
    var center = function() {
        for (var i=0;i<fcDialogs.length;i++) {
            $(fcDialogs[i]).dialog('option', 'position', ['center','center']);
        }
    }
    //attaching the event handler to the scroll and resize events
    $(window).scroll(center);
    $(window).resize(center);
    //the function that will make a dialog stay in the center
    var fixcenter = function(el) {
        fcDialogs.push(el);
    }
 
    //function that will remove a dialog element from the fixedcenter list
    var unfixcenter = function(el) {
        for (var i=0;i<fcDialogs.length;i++) {
            if (fcDialogs[i]==el) {
                fcDialogs.splice(i,1);
            }
        }
    }
    //remember what were these functions before
    var osetData = $.ui.dialog.prototype._setData;
    var oinit = $.ui.dialog.prototype._init;
 
    //overwrite the ui.dialog methods with our own
    $.extend($.ui.dialog.prototype , {
        _init: function() {
            oinit.call(this);
            if (this.options.fixedcenter) {
                //enable fixedcenter
                fixcenter(this.element);
            }
        },
        _setData:function(key,value){
            if (key=='fixedcenter') {
                if (value) {
                    //enable
                    fixcenter(this.element);
                } else {
                    //disable fixedcenter
                    unfixcenter(this.element)
                }
            } else {
                //call the original _setData
                osetData.call(this,key,value);
            }
        }
    });
})(jQuery);

How to extend objects with jQuery

April 26th, 2010

Javascript is not a class-ical language language still we sometines need to extend objects like we do in class-ical languges. The basic language doesn’t provide a way for doing this, but can be written easily, the jQuery team have already written one.

jQuery.extend
A method of the global jQuery object(a.k.a $) that can extend any JavaScript object, even itself. The usage is simple:

jQuery.extend( target, [ object1 ], [ objectN ] )

It’s what we’d expect, it takes target and adds all the properties from Object1….ObjectN to it.

A basic example:
var foo = {a:1,c:3};
var bar ={b:2,c:4};
$.extend(foo,bar)
this will make bar look like this:
{a:1,b:2,cNote: it replaces existing properties, which may be a problem if we have nested objects and arrays, for that there is a special deep copy mode.

jQuery.extend( [ deep ], target, object1, [ objectN ] )

If deep is true it will merge the objects recursively. This method is generally good for extending or hacking objects, there is little else to say about this, because it’s documentation covers most of it’s usage, it can be found at: http://api.jquery.com/jQuery.extend/

How to lock dialogs to a position with JQuery

April 22nd, 2010

For some reason the jQuery developers didn’t feel that it was important to lock a dialog to a given position on the viewport, mainly because the real desktop application dialogs don’t have this functionality. Although this is true, but the problem is that desktop applications don’t have scrollbars, web applications do, and it can become inconvenient when the user accidentally scrolls.
Basically there are two ways to implement this, one is using the CSS position:fixed attribute, which is not supported by IE6, the other is to assign event handlers for scroll and maybe resize events.

Doing this is very easy:

$(window).scroll(function () {
    $(dialog).dialog('option', 'position', ['center','center']);
});

We need to bind to the window’s scroll event, and then simply set the dialogs position option, to make the dialog go to the desired position.

Alternatively we can hook in to the resize event too:

$(window).resize(function () {
    $(dialog).dialog('option', 'position', ['center','center']);
});

And we can also combine these two into one function to avoid code duplication.

var lockcenter = function () {
    $(dialog).dialog('option', 'position', ['center','center']);
}
$(window).srcoll(lockcenter);
$(window).resize(lockcenter);