Wednesday, April 30th, 2008
Category: Dojo
, Examples

Sam Foster has written up an example of using Dojo to create directory listings with keyboard shortcuts.
You can now tab over to the box on the top right, and filter your selections:
This tutorial shows you how to upgrade those plain vanilla pages to make getting around a little faster and along the way introduce you to some of the most useful bits of Dojo, and practical techniques for working with them. We’ll touch on: dojo.query, dojo.data, the dojo parser and dijit (specifically the FilteringSelect widget.)
This is a great look at how things work in Dojo land, including the interesting code embed technique:
HTML:
-
-
<div style="display:none" jsId="linksStore"
-
dojoType="dojo.data.ItemFileWriteStore">
-
<script type="dojo/method" event="preamble" args="params">
-
params.data = {
-
identifier: "id",
-
items: []
-
}
-
</script>
-
</div>
-
Friday, April 25th, 2008
Category: JavaScript
, Showcase
, Examples
, Browsers
, Testing
, Performance

Steve Souders has released a nice little tool called Cuzillion which has the tag line of ‘cuz there are zillion pages to check, although it could also be that there are a zillion ways to do Web development!
The tool lets you test out different techniques for optimizing performance in browsers, and these tests can be saved and shared by the community.
Steve explains how the tool came about:
I’m constantly thinking of or being asked about how browsers handle different sets of resources loaded in various ways. Before I would open an editor and build some test pages. Firing up a packet sniffer I would load these pages in different browsers to diagnose what was going on. I was starting my research on advanced techniques for loading scripts without blocking and realized the number of test pages needed to cover all the permutations was in the hundreds. That was the birth of Cuzillion.
Here Steve talks about some examples:
A great example of how Cuzillion is useful is looking at the impact inline scripts have when they follow a stylesheet in Internet Explorer. Typically, a stylesheet followed by any other resource results in both resources being downloaded in parallel in Internet Explorer. (In Firefox stylesheets block parallel downloads, so this performance optimization is only applicable to IE.) Here’s a Cuzillion page that shows this: stylesheet and image downloading in parallel. Both the stylesheet and image are configured to take 2 seconds to download. Since they download in parallel the page takes about 2 seconds to load as shown by the “page load time”.
But look what happens if we put an innocent inline script between the stylesheet and image: stylesheet, inline script, and image. Now, in Internet Explorer the stylesheet and image are downloaded sequentially, which means the page load time goes from 2 seconds to 4 seconds. If the inline script is simply moved above the stylesheet the two resources are downloaded in parallel again, and the page load goes back down to 2 seconds: inline script, stylesheet, and image.
This was a great discovery. But immediately my officemate asked if inline style blocks had the same effect. No problem. With Cuzillion I just do some clicks and drag-and-drop, and can test it out: stylesheet, inline style block, image. It turns out inline style blocks don’t cause stylesheets to block downloads.
The findings from a tool like Cuzillion are really valuable. The lessons learned from poking at inline scripts and stylesheets can save hundreds of milliseconds on page load times. And it’s a common problem. eBay, MSN.com, MySpace, and Wikipedia all suffer from this problem.
Much thanks to Google for letting me release this code under Open Source. It’s not currently on Google Code but if you want to contribute let me know and I’ll do that. Try it out and send me your feedback. And share your insights with others. We all want the Internet to be faster!
Steve is talking at Web 2.0 Expo today at 1:30pm in room 2002. If you are in town, check it out and see Cuzillion in action!
Tuesday, April 22nd, 2008
Category: JavaScript
, Component
, Examples
, Yahoo!
, Framework
I've been talking about event driven application design in JavaScript in January last year and inspired Caridy Patiño to write his Bubbling Library based on these ideas.
Caridy now upped the ante a bit by talking about decoupling using the bubbling library over on the YUI blog.
In essence, his solution allows you to have custom events on application modules and listen to them independent of execution order or availability. Simply using custom events can get you in a pickle if you make yourself dependent on their order. With the decoupling solution proposed by Caridy this becomes one less issue to worry about.
Category: JavaScript
, Examples
, Yahoo!
Mitchell Amihod has a nice little post talking about the features in YAHOO.lang which is probably the least mentioned part of YUI.
He starts out with the type checking functions such as like isNull(), isUndefined(), isValue(); then he does for a trim().
Did you know that YUI had a mini template language in the form of substitute?
JAVASCRIPT:
-
-
// simple
-
YAHOO.lang.substitute('Hello {world}', {'world':'earth'});
-
-
// process
-
var processText = function(key, value, extraInfo) {
-
if(!YAHOO.lang.isNull(extraInfo)) {
-
return extraInfo;
-
}
-
return value.toUpperCase();
-
};
-
YAHOO.lang.substitute('Hello {world Venus, Jupiter}', {'world':'earth'}, processText);
-
No DHTML library would go without wrapping the setInterval/Timeout calls:
JAVASCRIPT:
-
-
var foo = {
-
count :0,
-
'method' : function(data) {
-
this.count++;
-
if(this.count == 10) {
-
timer.cancel();
-
}
-
console.log(this.count);
-
}
-
}
-
var timer = YAHOO.lang.later(1000, foo, 'method', [{data:'bar', data2:'zeta'}], true);`
-
And then you have the need to merge. If you are used to Rails development you will get addicted to passing hashes around and using merge type operations to do your deed.
JAVASCRIPT:
-
-
var myAwesomelWidget = function(oConfigs) {
-
oConfigs = oConfigs || {};
-
var defaults = {
-
'awesomeness' : '11',
-
'shiny' : 'high',
-
'sparkle' : 'high'
-
}
-
-
var combinedConfigs = YAHOO.lang.merge(defaults, oConfigs);
-
//Shiny is now set to low, everything else in combinedConfigs is set to the defaults
-
};
-
myAwesomelWidget({'shiny': 'low'});`
-
Monday, April 21st, 2008
Category: JavaScript
, Library
, Examples
, JSON
Jacob Seidelin went on a ( crazy :) ) mission to create a pure JavaScript video player that didn't use Flash:
My first thought was to read binary video files using a technique like the Andy Na posted about here, figuring that there must be some really simple to parse video formats around, but I soon changed directions and decided to make up a whole new video format. Enter.. JSONVid. Using a player like mplayer, it is easy to export all frames in a movie clip to individual jpeg files, and using whichever language you prefer it is also fairly trivial to collect these files, base64 encode the bunch of them and throw them all together in a nice JSON file (I used this PHP script).
The format uses good ole data: URLs, which are finally supported in IE with version 8:
JSON:
{
frm : "JSVID", // format id tag
ver : 1, // version number of format
width : 320, // width of video
height : 240, // height of video
rate : 15, // framerate (frames per second)
frames : 495, // number of frames in file
data : {
video : [ // here comes 495 data:uris containing base64 encoded jpeg image frames
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7gAOQWRv ... ",
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7gAOQWRv ... ",
...
]
}
}
Then he created the player:
First strategy was to create an Image object for each frame and render it on a canvas element using drawImage(). That worked fine and performance was nice (although Opera used a lot of CPU), but I figured I'd try just using a regular image tag and just change the src property to another data:uri each frame. The change was barely noticeably in Firefox and Safari and it ran a bit better in Opera, so I lost the canvas and stuck with plain old images.
Now, it seems that Firefox will eat up all the memory in the world if you keep throwing new data:uris at the same image tag, which led to another change, so for each frame a new Image object was created and saved for later and as the video played, the previous frame Image was replaced by the new Image object. That seemed to work, but introduced an annoying delay as all these Image objects were created before playing, so I ended up moving the Image creation to actual render cycle where it simply checks if the frame Image has already been created, and if not, creates it.
You can now get going with HTML such as:
HTML:
-
-
-
-
<script src="jsvideo.js" type="text/javascript"></script>
-
</head>
-
-
<div videosrc="myvideo.jsvid" videoautoplay="true"></div>
-
</body>
-
</html>
-
There are a couple of tests to play with. It was also pointed out that maybe an animated gif/png would be a choice (without controls), and of course, Flash is still the best choice here, until we get video support in most browsers.
Tuesday, April 1st, 2008
Category: Examples
, CSS
, SVG

Torrey Rice took Safari 3.1 and the new CSS Animations feature, and mashed it up with SVG to create a fisheye demo.
All the functionality through CSS:
CSS:
-
-
.dock img {
-
width:50px;
-
padding:10px;
-
float:left;
-
position:relative;
-
display:block;
-
-webkit-transition:width 0.5s ease-out, top 0.2s ease-out;
-
}
-
-
.dock img:hover {
-
width:100px;
-
}
-
-
.dock img:active {
-
top:-40px;
-
}
-
-
.dock img:hover + img {
-
width:70px;
-
}
-
Jeff Schiller then asked to see the example using the standard SMIL, which has been turned on (all beit a subset) on WebKit nightly to pass Acid3.
-38461538461538000 rating from 26 votes
Thursday, March 20th, 2008
Category: JavaScript
, Examples
, Aptana
Dealing with file uploads can be a test of a Web framework. I personally long for the input type="file" to be improved with items such as multiple="true" for multiselection, let alone showing the status of the upload (20% complete).
The Jaxer folks have posted on Easy File Uploading using Aptana Jaxer which shows how you can tinker in JavaScript to get everything you need in a very simple way:
To receive the data from the form when submitted we put some Jaxer code into the page the form will be submitted to. The code below should be in script block with a runat = 'server' attribute, which makes the code run serverside and doesn't present it to the client so you don't expose any serverside filenames or folder structures.
HTML:
-
-
<script type='text/javascript' runat='server'>
-
var message = "";
-
-
for (fileCount=0; fileCount <Jaxer.request.files.length; fileCount++){
-
var fileInfo = Jaxer.request.files[fileCount];
-
-
var destinationFilePath = Jaxer.Dir.resolvePath(fileInfo.originalFileName);
-
fileInfo.save(destinationFilePath);
-
-
message += "<br>" + [
-
"Saved to : " + destinationFilePath
-
, "original filename : " + fileInfo.originalFileName
-
, "temp filename : " + fileInfo.tempFileName
-
, "contentType : " + fileInfo.contentType
-
, "size : " + fileInfo.fileSize
-
].join("<br />");
-
-
}
-
document.write(message);
-
</script>
-
Tuesday, February 19th, 2008
Category: Examples
, Ext

Jack had posted a couple of entries back to back in the world of Ext.
First, he has been playing with Air again, and quickly wrapped the Ext 2.0 docs in Air, which would have been helpful when I was hacking the Ext toy on the plane:

Second, he has been playing with Vista gadgets and Ext and created a forum watcher that has the following gadget special code:
JAVASCRIPT:
-
-
function changeDock(){
-
if(System.Gadget.docked){
-
System.Gadget.background = 'images/docked.png';
-
var bd = Ext.getBody();
-
bd.setSize(130, 250);
-
bd.addClass('docked');
-
cm.setHidden(1, true);
-
cm.setRenderer(0, renderTopicMini);
-
grid.setPosition(4, 4);
-
grid.setSize(121, 241);
-
toggleDetails(null, false);
-
}else{
-
System.Gadget.background = 'images/undocked2.png';
-
var bd = Ext.getBody();
-
bd.setSize(528, 383);
-
bd.removeClass('docked');
-
cm.setHidden(1, false);
-
cm.setRenderer(0, renderTopic);
-
grid.setPosition(14, 14);
-
grid.setSize(494, 349);
-
cm.setColumnWidth(0, 350);
-
toggleDetails(null, true);
-
}
-
}
-
-
System.Gadget.onUndock = changeDock;
-
System.Gadget.onDock = changeDock;
-
Wednesday, February 13th, 2008
Category: JavaScript
, Accessibility
, Examples
, Security
, Unobtrusive JS
I've just come across a solution for badges on web sites that makes it terribly easy for implementers. The idea is that the implementer could add a badge wherever they want in an HTML document, choose the look and feel and add a message to be shown. The implementation code is the following:
HTML:
-
-
<script src="badge.js" size="small" skin="blue">Brandname
</script>
-
The badge script then replaces the script node with the badge using the settings defined for each script include. Clever, right? Well, almost. Security concerns and invalid HTML aside (the attributes - content inside a script is valid and should be ignored according to the W3C when a src attribute is present) there are many more issues with this:
- you need to loop through all script nodes, read the info and create the correct badge - this can get slow
- the badge.js script gets called over and over again, even if it is only needed once (granted, it will be cached)
- every script inside a body makes the rendering engine stop, pull the src and try to execute either that or the content of the node - this makes for terrible performance.
I've written up an example of how the above works and three alternative solutions that work around these issues.
What do you think? Should the ease of implementation be the success factor or the performance for the end user?
Thursday, February 7th, 2008
Category: JavaScript
, Dojo
, Examples
I am learning at lot at the Dojo Developers Day one. Whenever I met Dojo folks I get the impression that there are 55 gems in the library that I have no idea about!
One of them is Neil Roberts implementation of the Django template language in JavaScript.
His work lives in dojox.dtl and you can check out a simple demo that renders, and rerenders a page with new content as you add it: