Tag Archives: javascript

Server-side JavaScript and working with ActiveJs

In my effort to make it easy to contribute to ToDoSo, I have chosen JavaScript as the server side technology for this project.

Although Ruby on Rails is the technology of choice for most Web applications that appeared lately on the Internet [1. twitter - most job offers require to be familiar with this framework -, github, uservoice, zendesk, lighthouseapp - all of them using the Ruby on Rails cloud engineyard - and getsatisfaction - created by rubyredlabs - to name a few], it requires to learn not only HTML, CSS and JavaScript for the client side development but an additional technology for the server side development (a new language and a complete Framework in the case of Ruby on Rails).

Some would argue that Ruby is a really simple and rather self explaining language, that Ruby on Rails is a mature framework and altogether they make Web development a breeze once you know how to use it. I agree, but I also know that JavaScript is a great language as well and that it would lower the technological barrier if it was possible to use it on the server side with a framework comparable to Ruby on Rails.

There are already a large number of server-side JavaScript interpreter listed on wikipedia and on the ServerJs project page of Mozilla. There is also Jaxer, developed recently by Aptana. I recommend to watch the introductory videos on aptana.tv to have a brief overview of what is possible with it, but in brief its main features are:

  • the possibility to access and modify the DOM on the server before it is sent to the client (you can even use the canvas API to dynamically create images)
  • the possibility to share code between the client and the server sides (you only have to write your form validation logic once)
  • the possibility to call server side function from the client side (using invisible ajax requests)

Most of those server-side interpreters are based on open-source JavaScript interpreters that are to be found in modern web browsers [2. SpiderMonkey and V8 mainly, I haven't heard about any based on SquirrelFish or TraceMonkey so far but it seems that Jaxer will switch to the latter] which means that they benefit from the same speed improvements that we saw recently in Web browsers.

There are also few JavaScript MVC frameworks similar (at least in the spirit) to Ruby on Rails built on top of this server technologies: the most advanced ones seem to be Helma NG and ActiveJS. Both projects however, still seem to be in an early stage of development. Once again it could take ages to make a deep comparison of those and it wouldn’t help to get ToDoSo real. Instead you’d rather choose one and stick with it for better or for worse.

I’ve chosen ActiveJS because it is built originally for Jaxer and thus doesn’t require any configuration to get started if you are developing with Aptana Studio. Moreover, the ORM layer of ActiveJS (ActiveRecordJS) offers an abstraction not only to MySQL and SQLite databases (on the server side) but also to client-side persistence such as Google Gears or the SQLite database that is to be found in Safari and the iPhone Web browsers. Its route component is similar to the Ruby on Rail’s one but also offers deep linking on the client side, in the Jaxer spirit.

Hacking into ActiveJS

Because ActiveJS is still young, it is really likely to miss some features that might be important for your project and the best solution will be to hack into it instead of waiting for someone else to do the job. So here is how to configure a development environment to be able to build ActiveJS from sources (as a reminder for myself):

  1. I assume you are developing with Aptana Studio and you have the Jaxer and Git plugins installed.
  2. Fork the ActiveJS repository on Github.
  3. Import it as a project in Aptana (File > Import > Git Repository, choose git+ssh as the protocol and don’t change the username)
  4. Ruby needs to be installed in its 1.8 version because the build script depends on ftools, which is deprecated in ruby1.9. With Ubuntu and probably other linux distribution, the ruby-dev package is required as well.
  5. The package rubygem is then required to install most dependencies of the build script: json, packr (beware, this might soon be replaced by YUI) and rdiscount. In any case look at the beginning of build.rb to find the dependencies of the script.
    [code lang="shell"]$ sudo gem install rdiscount [/code]
  6. Remember to configure your editor to use 4 spaces instead of tabs and try to respect the coding style.

Et voilà! You’re ready to change the files in the src folder, build active.js, test your modifications and send pull requests to the original branch.

[code lang="shell"]
$ ruby1.8 ./build.rb compress
[/code]

My first tasks will be to improve the relationship features because it doesn’t behave as a proper ORM layer currently and to add support of HTML5 elements to the view component.

New mockups and keyboard navigation

I’ve added mockups demonstrating the appearance of the presentation when an embedded one is maximized. Since it is pure HTML, it is not going to be opened in a different window unlike a Flash video, it is rather going to overlay all the page.

todosOverlay, the overlay plugin used on the intro page of ToDoSo, is now an independant project since it tends to become a full featured overlay plugin. It is now possible to use the keyboard for navigation and I got rid of some graphical glitches. I’m quite proud of its look & feel. The idea of using buttons looking like keys  is likely to be used again in ToDoSo since it seems like a great way to make keyboard shortcuts discoverable.

http://www.todoso.org/image/keyLeft.png

You know everything about cookies, don't you ?

Cookies are used on the Web for almost 15 years now, and despite their numerous flows and the emerging alternatives brought by HTML5, developers still resort to them, mainly for their ease of use and consistent implementation across browsers. For example, as you might have noticed, the background colour of this page changes over the time. To keep the colour up to date across the different pages, the colour value is stored in a cookie. When a user is offered controls to increase or decrease the font sit on a site directly from a Web page, the same mechanism is used.

So far, the best technical documentation about cookies available on the Web was the one found on QuirksMode. It still appears as the number 1 result on google for the query: cookie Javascript. The related page on Wikipedia is a good source of information concerning all the drawbacks and the alternative to cookies. Although there are suitable alternatives when it comes identifying a client from a server, there is no widespread solutions working purely on the client-side (but I urge you to use a modern web browser and the gears plugin to get yourself ready for the next generation of Web applications). Anyway this documentation and the proposed algorithms are quite old, and the purpose of this post is to give the small update it deserves, and it will stick to client side use of cookies.

Writing a cookie

Cookies are just little text files managed by the browser that can be used to store key/value pairs. The maximum size of a cookie file for a given website is 4ko, preventing it to be used for anything else than small strings (a colour code, a font-size, a preferred language are perfectly fine). And this is the basic code to write your first cookie:

var cookie = "fontsize=19px";
document.cookie = cookie;

You just append a string composed of a key and a value separated by an “=” sign to the cookie property of the document.

By default, this cookie will be stored only as long as your browser remains opened and it will be available only on the same path of the same domain. If the address of the page is http://en.wikipedia.org/wiki/HTTP_cookie for example, cookies written from this page will be only available on pages with addresses beginning by en.wikipedia.org/wiki/, everything before the first “/” being the domain, and the rest being the path.

By the way, during the celebration of the 20th anniversary of the World Wide Web, Tim Berners-Lee admitted that he regretted the way Web addresses were constructed, and that the domain should start with the more general elements. Applied to the previous example, this would have lead to: /org/wikipedia/en/wiki/… (bringing the folder/sub-folder metaphor to the Web).

It is possible to change those defaults by adding parameters at the end of your cookie String.

Expiry date

It is possible to specify explicitly the date when the cookie will be trashed by the browser, using the expires parameter and a Date object serialized by the Date.toUTCString() method (and not the deprecated toGMTString one):

var day = new Date(),
expiryDate = "expires=" + day.toUTCString();

In modern browsers, it is alternatively possible to set the max-age of a cookie in seconds, but this parameter is unfortunately unavailable in Internet Explorer (just like so many other things that would make the Web developer’s life easier).

Path and domain

It’s a good practice to set the path to the highest level:

var path = "path=/";

I can’t foresee any serious security issue resulting from this practice (considering that cookies should never be used to store critical data). And on the other hands you are likely to be unable to erase a particular cookie written by a script not specifying any path.

If there is no sub-domains for your website, the domain parameter is not useful. But in the Wikipedia example, the domain should be set as follows to be able to use the cookies across sub-domains:

var domain = "domain=wikipedia.org";

All-together

Writing a cookie with those parameters can be achieved with the following code:

var day = new Date();
document.cookie = "fontsize=19px" +";"+
"expires=" + day.toUTCString() +";"+
"domain=wikipedia.org +";"+
"path=/";

As you can notice, parameters should be separated by a “;”. Note that so far the Date used is a new, unmodified date, which represent the current date. Setting a expiry date to the current date is not gonna make your cookie last long. The solution will be provided in the scripts.

It is not possible to write two cookies at a time.

document.cookie = "fontsize=19px; fontcolor=#0000FF";

This code would actually write only the first key/value pair. You have to write the second cookie on a separated line beginning with document.cookie. Considering the parameters string to add to each cookie, the need of code factorisation is easy to understand.

Reading a cookie

Reading a particular cookie value can be achieved by reading the cookie string of the website and extracting a single value pair using a regular expression based on a key.

result = new RegExp("(?:^|; )" +key+ "=([^;]*)”).exec(document.cookie);
var value = result[1];

Special characters

In order to be able to read and write values potentially containing special characters (such as a “;” that would split your value), the value should be encoded before being written and decoded after being read.

document.cookie = encodeURIComponent("special=abc;def");
result = new RegExp("(?:^|; )" +"special"+ "=([^;]*)”).exec(document.cookie);
var value = decodeURIComponent(result[1]);

Overwrite and delete cookies

To overwrite a cookie simply write a new cookie with the same key.

document.cookie = "key=firstValue";
document.cookie = "key=secondValue";
// When reading "key", you'll find "secondValue"

The best way to erase a cookie is to overwrite it with an empty value and a past expiry date

var day = new Date();
// set the date to yesterday
day.setDate(day.getDate() -1);
document.cookie = "key=" +";"+
"expires=" + day.toUTCString();

The scripts

Using the previous pieces of code, it is possible to create a small cookie library that will handle writing/reading/erasing a cookie with a single function.

function cookieLib(key, value, expiryDay) {
  // If there is not just a key, the function is used to write a cookie
  if(arguments.length >1) {
    // But if the value is null, the function is used to erase a cookie
    if (value === null) {
      value = '';
      expiryDay = -1;
    }
    // If the date parameter is a number,
    // create a date from today + this number of days
    if (typeof expiryDay == "number") {
      var day = new Date();
      day.setDate(day.getDate() + expiryDay);
      expiryDay = day;
    }
    // Create the cookie string
    document.cookie = [
      key , '=' , encodeURIComponent(value),
      '; expires=' , expiryDay.toUTCString(),
      '; path=/'
    ].join("");
  // If there was only a key, the function is used to read a value
  } else if(result = new RegExp("(?:^|; )" +key+ "=([^;]*)")
           .exec(document.cookie))
    return decodeURIComponent(result[1]);
  return false;
};

Remember that cookies are only meant to store string values. If you want to write a number, remember to parse it back to a number after reading it.

I’ve also turned this cookie library in a plugin for the famous jQuery library, check the code of jquery.cookie on github.

Changes in VML for IE8, or "what feature can the IE dev team break for you today?"

The final version of Internet Explorer 8 has been released by Microsoft on the 20th of March. It’s packed with a fully CSS2.1 compliant rendering engine, separate process per tab (just like in Google Chrome, good for stability, bad for memory consumption), performances are claimed to have improve, it introduces new features that will benefit the user such as Accelerators and Web Slices (available in Firefox with the WebChunks addon), as well as interesting features that will benefit the developer, such as a debug tool inspired by Firebug, the onhashchange event and some other interesting things. What as not been included in Internet Explorer 8? The list is unfortunately too long:

  • A Javascript Virtual Machine that could compete with the ones shipped by other browser vendors. The performances of Safari (squirrelfish extreme), Chrome (V8), Firefox (Tracemonkey) and Opera (Carakan) are still far better. But why would Microsoft create a Web browser shaped for the next generation of Web Applications? They are actively promoting their Software As A Service platform and Silverlight, their own Rich Internet Application framework because they can make much more money by forcing developers to adopt their technologies than by making any contribution to the Open Web.
  • <canvas>, <svg> or <video> are missing, and again, this isn’t a big surprise. There is everything you need in Silverlight for vector graphics, audio and video , would the salesman say.
  • Only little support of CSS3. Considering the credit crunch this can actually be seen as an advantage. How would the developers justify their pay if they could use border-radius, border-image, text-shadow and such, straight away, without spending countless hours working around Internet Explorer weaknesses?

Now it’s time to get onto what they managed to break without telling anyone: VML. VML stands for Vector Markup Language, an XML based language aimed at describing vector graphics. It has been submitted to the w3c in 1998 and begins with the following status:

This document is a submission to the World Wide Web Consortium.  It is the initial draft of the specification of VML.  It is intended for review and comment by W3C members and is subject to change.

At the same time, Adobe proposed to the w3c a language with similar purposes: PGML. Eventually, the two standards were merged into what is now SVG… But Microsoft made the choice to ignore this standard and to implement only their original proposition into their browser. Considering the market share of Internet Explorer at that time (around 95%), was there any reason to bother about Web standards? The legacy of this regretted market share is that developers now have to deal with two standards when it comes to vector graphics on the Web, since SVG is the one used in every other browser. Fortunately, there are abstraction layers that allow Web developers to use such features with a lowest common denominator approach such as Dojo.gfx or raphaeljs. But sometime you need to get your hands dirty and to use directly VML for performance or technical reason. This is the case in my border-image script where I’m using only one VML element: image. This was before the first Internet Explorer 8 beta came out…

Although the VML specification hasn’t undergone any improvements or modifications since its publication back in 1998, Microsft development team felt like considerably changing the way their own standard should be handled:

  • The namespace declaration has to take a second argument to be functional:
    document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', "#default#VML");
    instead of simply:
    document.namespaces.add('v', 'urn:schemas-microsoft-com:vml');
  • The selector for the behaviour rules needs to be slightly modified (more information follows).
  • For a standard compliance purpose, when setting dimensions or position of an element, the unit no longer defaults to ‘px’. It has to be explicitly specified
  • It is no longer possible to create a VML element outside of the DOM:
    var myFragment = document.createDocumentFragment();
    myFragment.insertAdjacentHTML('beforeEnd',
    '<v:rect id="myRect" fillcolor="blue" style="top:10px;left:15px;width:50px;height:30px;position:absolute;"></biv:rect>'
    );
    document.body.appendChild(myFragment);

    This rect element will not be displayed! And don’t try to modify its CSS properties with the developer tool, you are likely to crash the tab or even the browser, if you’re lucky. Fortunately, there is an easy fix for this bug: you just have to copy the outerHTML of the element into itself:
    var myRect = document.getElementById('myRect');
    myRect.outerHTML = myRect.outerHTML;
  • It’s no more possible to use % unit! This one is my favourite. The advantage of vector graphics is that they can be scaled without quality loss. Now tell me how you scale a graphic from which all components dimensions and position are set in pixels! You have to resort to using the onpropertychange event to recalculate one after the other those values each time you want to resize your graphic. But there is a lot of case where you simply can’t fix this bug. For example, if you had an rectangle in a div: the div has no dimensions and scales with its content, and you want the height of your rectangle to scale with the div. There was a time when it was possible to simply set the height of the rectangle to 100% (providing the position of the div is relative, of course). But it was probably too easy after all.
  • It’s no more possible to use the getAttribute method to access the values of a particular attribute of your element.
    var myRect = document.getElementById('myRect');
    // Not working in IE8
    myRect.setAttribute('fillcolor', 'green');
    // Still working everywhere
    myRect.fillcolor = 'green';

Remarkably, none of this change has been announced by the IE dev team, as far as I know. The only announcement made about VML can be found on a blog post:

Generic CSS prefix selectors are no longer supported in IE8 Standards Mode in order to provide standards-compliant CSS parsing. Most often, this affects pages trying to use CSS to attach behaviors to VML elements. This can cause a script error if set dynamically, or a silent failure when hard-coded into the CSS of a page. Ultimately the rule is not applied, leading to effects such as VML not displaying on a page.

v:* {
behavior: url(#default#VML);
}

SOLUTION: Explicitly specify each tag name you want to match when using CSS prefix selectors.

v: polyline
v: line {
behavior: url(#default#VML);
}

Can you spot the problem? There is actually nothing wrong with the * selector in CSS from a standard compliance point of view, to prevent the script from crashing if you set it dynamically, you simply have to put a space between the “v:” and the * (you need two backslashes in javascript):

v: * {
behavior: url(#default#VML);
}

I don’t really know what to think about that. On one hand it seems that some of this changes are just bugs (elements are still appearing in the developer tool with correct dimensions and position, they are simply not rendered), on the other hand, if they wanted to finish off VML and force developers to work with Silverlight, they couldn’t do it any better…

Just for fun, take a look at the VML documentation on MSDN, here is what you can still read:

  • About the height property:
    Units: A number with an absolute units designator (cm, mm, in, pt, pc, or px) or a relative units designator (em or ex). If no units are given, pixels (px) is assumed.
    Percentage: Value expressed as a percentage of the parent object’s height.
  • About the last parameter of the namespaces.add method:
    sUrl: Optional. String that specifies the URL of the element behavior to import into the namespace. Specifying this parameter is the same as calling the doImport method.

I learned about this namespace change in an obscure bug report in Microsoft connect. I had to figure out the rest by myself. I’m just afraid that I discovered those bugs too late. Now that Internet Explorer 8 has been made publicly available, there is only few chances for any change to be introduced in the rendering engine…

Update: Following the related post on ajaxian, Christian Effenberger pointed out that the setAttribute no longer work. I also want to state that the most obvious and easy way to fix all those bugs at once is to use the IE7 meta-tag:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

IE7 is still the most common Web browser according to its market shares, so you have to make your website compatible with it (still painful, but nothing compared to its predecessor). Once your website is compatible with IE7, add this meta-tag and you will have compatibility with IE8 for the same price, with good ol’ VML implementation. Disclaimer: I do not recommand browser sniffing or browser hacks and should not be held responsible for bad use of the previous advice, period.

Update2: Changed the IE7 meta-tag and the link to the announcement on the IEBlog, thanks to dflock.