Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Nifty stuff #1

Nifty stuff is a series of blog post delving into nifty stuff I have made and or discovered. Since I'm kinda shary I share my discoveries, for your benefit I hope..
In this first «nifty stuff» I take a look at 4 (four) quite different nifty things, this time in the world of web-development.

  1. Coda 2 Web Toolkit plugin. Last month Panic released Coda 2, their all in one window web-development platform/editor. Almost instantly a flurry of plugins and syntax modes appeared for this awesome editor. One of them is "Coda PHP & Web Toolkit", which is what the name implies an extension for Coda 2 which allows you to tidy, minify and lint you HTML, CSS and JavaScript code. It can also do a bunch of crap with PHP, so I guess it would be great for that as well. I use it primarily for linting JavaScript and tidying CSS...and it's awesome!
  2. jQuery ++. This is an extension to jQuery which adds some cool features like comparison helpers and better event handling. Most of all I like that the animate method will support CSS transitions after adding this library (it's not CSS animations which the doc actually say). This alone makes it worth using this if you are dependent on jQuery.
  3. Printing and HTML 5 elements. Since there are a lot of old shitty browsers like Internet Explorer 8 or worse out there and these does not support HTML structural elements, we need libraries like Modernizr with HTML5Shiv. This makes it so that the older crap shit browsers don't fall over and flop around like a slimy fish on land when they encounter something groundbreaking like a "section" tag. However, the regular HTML5Shiv does not fix this issue for printing, you need to use HTML5Shiv with printshiv for this...so remember that..okay
  4. Native query selectors. You have probably used jQuery to select DOM elements right? But did you know that jQuery actually uses a native (built into the browser) method for selecting the element if this method is available? There are two methods called "querySelector" and "querySelectorAll". Like jQuery, these methods take CSS style selector strings and returns either the first or all elements as a NodeList (kinda like an Array). These methods are supported in all modern browsers and even in IE 8 or newer!!! So if you're not supporting below IE 8 (which you shouldn't!) you might not need the overhead of jQuery at all.

JavaScript tap event for touch devices

JavaScript touch events are awesome and they are standardized (Candidate recommendation) by the W3C, making them safe to use for building your touch enabled web-apps. There are 4 touch events:

  1. "touchstart" - When a finger in placed on the screen
  2. "touchmove" - When a finger moves on the screen
  3. "touchend" - When a finger is lifted from the screen
  4. "touchcancel" - When touch is canceled, like when an alert appears or a call comes in.
But, what constitutes a "tap", like a "click" in the mouse model you might wonder. There a several answers to this. A tap might be simply a "touchend". But, what if the user places a finger on a button and then flicks the screen up so that the button goes off screen, now the button will fire a "touchend" when it's off screen. And what if the user holds a button for a long time and then lets go, should that fire an event?

To combat these issues I've created a Javascript library (and a jQuery plugin) which will handle all of this for you. You simply add the library or plugin to your project and then you add the spanking new "tap" event to your button or what have you. The "tap" library will then try to take care of the issues mentioned above.

Using it is simple:
 var tapHandler = function(e){  
    //Do something  
 }  
 document.getElementById('aDiv').tap(tapHandler);

Take a look at the documentation inside of the source files and of course, look at the demo.


Form input placeholder shiv

As part of the HTML 5 form features, the attribute "placeholder" was introduced for input elements supporting text input (including password). This is awesome and does indeed make form input elements not only more accessible, but it also paves the way for "label less" UI on devices with no so much screen real-estate. However, as with all new things HTML 5 this too is not fully supported on every major browser. Enter the not so elegantly named "placeholderShiv".

I wrote this library to enable the "placeholder" feature in every browser. It will basically grab all the valid input elements and append to them functionality which will mimic the native placeholder feature. All you need to do is to assign values to the input elements and add the library of your choice. This value will be turned into a placeholder text. Try the demo to see it in action.

«PlaceholderShiv» comes in three versions, a Coffeescript version, a JavaScript version and a jQuery plugin. The Coffeescript and the JavaScript ones does not have any dependencies on any other libraries and they are somewhat faster than the jQuery plugin. However, the jQuery version will support browsers which does not implement "addEventListener" and it is somewhat easier to use if you're already using jQuery.


Extending the Modernizr.prefixed method

Starting with version 2.0 the awesome feature detection js library Modernizr includes a method called "prefixed". In short, this method will give you the correct prefixed version of a CSS 3 property which still requires this. E.g: -webkit, -moz and so on. Used in conjunction with the jQuery library you can use Modernizr.prefixed for typical tasks like adding a transition to an element in script without having to clutter up your CSS with a gazillion lines of vendor prefixes.

However, the Modernizr.prefixed method will always return the JavaScript version of the style property. Modernizr.prefixed('transform') will return "WebkitTransform" in a Webkit browser. If you are using jQuery.css() this might not be a problem as jQuery.css() understands this format as well, if it's passed as the property (first parameter). However the prefixes might also be needed as the actual value of an style property. Consider the following:

 $('#myDiv').css(Modernizr.prefixed('transition'),Modernizr.prefixed('transform') + ' 1s linear');  

This snippet will attempt to set a transition on the "myDiv" HTML element using jQuerys´ "css" method and the Modernizr.prefixed method, but it will fail to do so. Why? Well, since jQuery is awesome it will allow us to pass "WebkitTransition" or "-webkit-transition" (if in a webkit browser) as the first parameter to the "css" method. For the second parameter jQuery.css() expects a CSS formatted string «-webkit-transform 1s linear», however the code above will generate «WebkitTransform 1s linear», which is not valid CSS and hence the entire method fails. What is needed is a Modernizr method which spits out a CSS formatted and prefixed string, let's call it "Modernizr.cssprefixed". Sadly this is not a part of Modernizr as of today, but the solution is given in the Modernizr.prefixed documentation, we only need a more convenient version of the RegExp given in the docs.

 Modernizr.cssprefixed = function(str)  
 {  
      return this.prefixed(str).replace(/([A-Z])/g,function(str,m1){   
         return '-' + m1.toLowerCase();   
      }).replace(/^ms-/,'-ms-');   
 }  

Now that we have this spanking new method we can update our line of code to:

 $('#myDiv').css(Modernizr.prefixed('transition'),Modernizr.cssprefixed('transform') + ' 1s linear');  

Voila, it works!

Getting you bearings with JavaScript on iOS

This post is an extension of my previous post on accessing the gyroscope in your iOS device from JavaScript for a web application. So be sure to read that one first or you'll probably get squat.

New in iOS 5 is the ability to access the compass using JavaScript. This is done precisely in the same way as with all other «orientation data». The «deviceorientation» event on the window object will (on iPhone 4 or newer running iOS 5 and newer) contain two properties related to the compass, these are:

  • «webkitCompassHeading» [0-360°] - Where 0 is magnetic north
  • «webkitCompassAccuracy» - How many degrees the heading is off (-1 if error)
So for the demo I'm using the same arrow as in the gyroscope post, except now with gorgeous «north» and «south» indicators added. The goal of the demo is to make the arrow point towards north. When you're done playing with it, take a look at the source and amaze at its simplicity.

Further reading:

Creating a simple WYSIWYG editor with HTML and JavaScript


An updated and better version of this post with a new and better demo can be found here: http://www.kinderas.com/technology/2014/2/18/a-simple-rich-text-editor

Wouldn't it be nice to provide the users of your website with a WYSIWYG rich text editor instead of boring forms and a bunch of textfields? Enter «contenteditable». This is a simple property which can be set on any DOM element, like divs, sections and so on. What it does it making the element writable for the user, directly inline with all your predefines styles and content.
contenteditable="true"
To get set up, set the «contenteditable» property of your selected element to "true". In my demo I'm using a «section» element, but as noted above, you can use any DOM element. And that is it actually. You now have a working rich text editor running on you web-page. You can use the keyboard shortcuts like «cmd+b» to make selected text bold and so on. But wait, there's more.
document.execCommand('bold',false,null);
This simple JavaScript command will allow you to programmatically make text bold and thats not all, there are a dozen of built in commands which can be executed on the selected text, for an overview take a look at the WHATWG specification.

When combining «contenteditable» with the HTML 5 storage APIs you can pretty easily make a powerful rich text editor for your users. Take a look at my simple demo to see how you can accomplish this. As a side note, iOS 5 brings support for «contenteditable» on mobile platforms as well.

Accessing the gyroscope and accelerometer using JavaScript

With the advent of "mobile" devices such as the iPad, iPhone and all the gazillion Android devices, an increasing demand for browser-applications to sport the features and functionality native applications arises. In this article I'll have a quick look at one of these features, namely «device orientation». First of all, take a look at the demo. In this demo I'm using the "deviceorientation" event listener of the «window» object to listen for orientation events. Orientation events are in short events triggered when your device is twisting and turning, sort of. In my iPhone, these events originate in the accelerometer and the gyroscope. For your phone this might be different, but it doesn't matter as the API's for accessing the data are pretty much the same and part of the «DeviceOrientation Event Specification». Note that this demo is only tested on the iPhone 4, so if you have something else it might not work. Let's get to it then.
window.addEventListener('deviceorientation', orientationHandler, false);

First of all we need to add an event listener for the «device orientation» event. This event is fired by the «window» object as mentioned above. We then simply set up our event handler.

function orientationHandler(e)
{
 image.style.webkitTransform = "perspective(500) 
rotateZ("+e.alpha+"deg) 
rotateX("+e.beta+"deg) 
rotateY("+e.gamma+"deg)";
}

There are three properties of the «orientation event» we want to get at.

  • «alpha» - This is rotation about the Z axis. In other words left and right rotation.
  • «beta» - This is rotation about the X axis. This means how much you are tilting the device towards you.
  • «gamma» - This is the rotation about the Y axis, or the angle of the device screen if you may.
There are also two other properties present in iOS 5 which gives you access to the compass and it's accuracy, but those are not used in this example.

The «perspective(500)» transform simply defines how "far away" from the object you are when it's rotated, or the depth if you like. Since the properties of the «device orientation» event correlates to the values handled by the CSS transform properties, no calculation is needed. Try it out! (Should work on iPhone 4 and iPad 2)

References:

HTML 5 Web Workers and image processing

One of the more exiting things we are getting via the new HTML specification is Web Workers. If you have no idea what Web Workers (lets call them Worker from now on) are you can basically think of them as "sandboxed" threads. By threads I do refer to threads as in «multithreading», an architectural feature of modern CPUs and operating systems. Workers allow us to run tasks separately from the main thread where all the drawing, animation and DOM manipulation is going on. This allows us to do calculations without leaving the impression on the user that the browser is "hanging". If you have worked with other "thread wrapping" technologies like Grand Central Dispatch (GCD) you will get Workers without fuzz, however Workers do have some limitations that other similar technologies don't have.

Workers limitations and usage
First of all, Workers are separate code blocks of JavaScript not found in the spawning script, kinda.. In most cases a Worker is a separate JavaScript file which you DO NOT refer to in you HTML script tags in the HTML document. However, Workers can also be defined inline through the BlobBuilder interface. In this post I will use only external Workers. Also, there are two kinds of Workers, «Shared» and «Dedicated». I will only use «Dedicated Workers» in this post.

Workers cannot access the following:
  • The DOM or the DOM APIs
  • The window object
  • The document and the parent object. 
A worker can access:
  • The «navigator» object
  • «XMLHttpRequest»
  • A read-only version of the «location» object
  • The Application cache
  • setTimeout(), clearTimeout() and setInterval(), clearInterval()
A Worker can also spawn other Workers and import external scripts via «importScripts()».

The demo (aka. the fun part)
For the demo this time I have created a simple web-app which loads and displays 3 pictures n times. You can randomize the position of the images by clicking the randomize button. You can pick the number of images displayed as well as their size. The two image manipulation buttons will grayscale and invert the images, if you check the checkbox the images will perform the randomize animation concurrently with the image processing. It's this latter part which calls for the usage of Workers.

The demo will show you how to spawn a separate Worker for each of the images, thereby allowing for concurrent processing and animation without much degradation in performance. I won't explicitly go through all the layout and animation code here, rather focusing on the usage of the Workers.

var worker = new Worker('DWGrayscale.js');
worker.addEventListener('message', function(e){
   ctxAr[e.data.index].context.putImageData(e.data.imagedata,0,0);
});
worker.postMessage(...imagedata...);

On line 126 - 133 within the grayscale function we create a Worker for each of the images, then we add a listener for the «onmessage» event allowing the Worker to communicate with the main thread. We finish off by posting a message to the worker using «postMessage» and passing the image data. These messages are the only way to communicate with a Worker. This means that we also need to implement this interface in the Worker itself.
addEventListener('message', function(e){
 var imageData = e.data.imagedata;
 //....process image data....
 postMessage(...imagedata...);
});
In the Worker «DWGrayscale.js» we grab the passed image data from the «data» property of the event. We then go on processing the image data, when done we post a message back to the main thread passing the image data which then in turn can be used to update the canvas element on screen.

Why not pass the Canvas element or at least the Canvas context?
Workers do not have access to the DOM, because it would not be thread safe. Workers are limited to passing object which can be serialized into JSON, which does not support cyclic objects. The Canvas element is a DOM element and the context is a cyclic object, hence we need to get the actual pixel array which we can pass back and forth to the Worker.

Take a look at the demo and the source code to learn in more detail how the demo was created.
Note also that you should probably run the demo in Safari as it has no limitation on the number of Workers concurrently running like Chrome has, also the animations uses the WebKit prefix and will not work in non WebKit browsers. So, please don't use this code in an production environment!

References:

Quicktip: Skewing an image with JavaScript and CSS3

Have you ever found yourself in a situation where you needed to skew a rabbit? If you haven't, you'll probably enter this place soon, so here I am to prepare you. The task is to skew an image on a HTML page using CSS and JavaScript. This could be attached to for instance a button click event. This is a one liner..
document.getElementById('myImage').style.transform = "skew(-15deg)"
The «skew» property of the «transform» CSS method takes degrees of skew as an input. Negative numbers will skew the image top right, bottom left and positive numbers..the other way around.
Note that in order for this to actually work, you will need to use vendor prefixes as the time of writing this post. For Safari (desktop and iOS) and Chrome (and Android) you would use «webkitTransform» for FireFox «mozTransform» and so on.

Scaling and rotating an elephant using JavaScript

This second post about «touch» is somewhat an extension to my previous post «Drawing by touching using JavaScript». However in this post the focus will be on «gesture events». A gesture event is an event which will fire when more than one finger is present on the screen. Due to the somewhat complex nature of the accompanying demo, I will not walk through it line by line, but rather focus on some key ares which are important when dealing with touches and gestures.
Step 1 is to take a look at the demo and read through my comments. To understand this you will need a basic understanding of object oriented JavaScript and I will not walk through that part of the demo in this post. What I will explain in some detail is how the gesture events work (to see how touch events work, refer to my previous post) and some nifty tricks you can do with event handlers and transforms. Oh..and you will be needing a touch device to test this thing. Let's get cracking then.

The basic functionality of this demo is to place images on the page which have some touch and gesture events applied to them. This will allow us to move, scale and rotate the images using gestures. An array «elephants» is used to keep track of all the images on the page. On line 70 (in the demo JavaScript file) an Object called «TouchImage» is defined. This object will keep track of all events and transforms associated with one image. We create a new «TouchImage» on line 52. This happens for every time you hit the «Create elephant» button. Then on line 99 - 104:
tImage.image.addEventListener('gesturestart', tImage, false);
tImage.image.addEventListener('gesturechange', tImage, false);
tImage.image.addEventListener('gestureend', tImage, false);
tImage.image.addEventListener('touchcancel', tImage, false);
tImage.image.addEventListener('touchstart', tImage, false);
tImage.image.addEventListener('touchend', tImage, false);

Now, this might look a bit strange, we're passing «this» («tImage» is a closure for «this») as the event handler for the listeners. This is because at line 117 we define a method called «handleEvent» on the «TouchImage». This is a magical method in JavaScript which will basically handle any event passed to it's object. Within this method we check to see if the caller is a function and if it is, we simply call it.
TouchImage.prototype.handleEvent = function(event)
{
 if(typeof(this[event.type]) === "function"){
  return this[event.type](event);
 }
}
This way we can extend the «TouchImage» object with methods called «gesturesstart» and so on, the same names as the events. An additional plus is that we stay within scope of the object, avoiding to pass closures around like rag dolls. Now to the gesture handlers. In contrast to «touch» handlers, there are only three «gesture» handlers: «getsurestart», «gesturechange» and «gestureend». Each of these will trigger only if there are more than one finger on the screen.
TouchImage.prototype.gesturestart = function(event)
{
 event.preventDefault();
 this.startRotation = this.rotation;
 this.startScale    = this.scale;
}
In «gesturestart» which triggers when a second finger is placed on screen, we capture the current scale and rotation values of the «TouchImage» in question.
TouchImage.prototype.gesturechange = function(event)
{
 event.preventDefault();
 
 this.scale    = this.startScale * event.scale;
 this.rotation = this.startRotation + event.rotation;
 
 this.applyTransforms(); 
}
In «gesturechange» we calculate the scale and rotation by using the start values and the changed values. The scale is multiplied with the new scale and the rotation is calculated by adding the start rotation to the current rotation. This works because both values in the change handler will give us the amount changed since the start event. Then we call the «applyTransforms()» method where the actual transform is done.
TouchImage.prototype.applyTransforms = function()
{
 var transform = 'translate3d(' + this.posX + 'px,' + this.posY + 'px, '+this.posZ+'px)';
 transform += ' rotate(' + this.rotation + 'deg)';
 transform += ' scale(' + this.scale + ')';
 this.image.style.webkitTransform = transform;  
}
The transform is done on all properties at the same time. You cannot separate them from each other, because we are in effect overwriting the entire transform style element each time something is changing. Do also note that we are in fact using «transform3d», which is quite different from the regular «transform». The reason for this is twofold. First, the «transform3d» will render the image on it's own 3D layer, at times triggering hardware rendering. This will yield a significant performance increase. Secondly, the «transform3d» allow us to stack elements in the «z-axis», hence we can move the active element to the front. We do this sorting by  calling the «sortDepth» method, which only sorts the «elephants» array.

That's the gesture events. Now, there are regular touch events in this application as well. These are used to move the «TouchImage» objects around the screen. I won't cover how this is done in detail here because it's much the same as in the previous post. However one thing to notice is that an offset is calculated in the «touchstart» handler. This is done so that when moving the image it tracks from the point where the user places her finger on the image. If we didn't do this the image would snap to 0,0 under the users finger when moved, making for an unexpected user experience. That's it and that's that!

Drawing by touching using JavaScript


An updated version of this post and demo is available here: http://www.kinderas.com/technology/2014/3/13/a-drawing-application


The web is no longer exclusive for desktop and laptop computers. With the introduction of the iPhone and the iPad Apple changed how we interact with the web. In the wake of Apples success with iOS devices we see the emergence of a slew of "handheld" devices. They are all different, some are small, others bigger and more powerful, however most of them utilize touch as a means of input. In this article I take a look at how we can create a simple touch enabled drawing application using only JavaScript and a tinsy-winsy bit of HTML 5.

First, you can try the finished app (with comments) and download the source code from here.

The first thing we need to do is to make sure that the user visiting our web-app is on a device which can understand touch events. This is pretty straight forward. We accomplish this by asking the «window» DOM element if is knows about one of the touch events.
if('ontouchstart' in window == false){
   alert('Sorry, you need a touch enabled device to use this app');
   return;
}
If this does not stop our script, we know that the current device supports the touch events we need. The next step is to prevent the screen itself from scrolling when you drag your finger across it. We need to do this because touch events «bubbles» in JavaScript. This means that all the parent elements will get a chance to handle the touch event after we have handled it in our function. So after we have handled the «touchmove» event in our canvas element it will bubble right up to the window element where the browser will try to scroll the window. PS: Sometimes you might want this behavior, for example when you're scrolling a page. For our demo, we don't need it. To disable page scrolling we listen for the «touchmove» event on the document element, then we flag the event as handled using «event.preventDefault()».

Now to the construction part. We need to create a canvas element.
var canvas = document.createElement('canvas');
canvas.width  = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
We now have a «canvas» element which is the same size as our entire page. Next up we need to create a context in which to draw for the canvas. A context is kinda like a page within a drawing pad. The context can receive JavaScript drawing commands as we will see later on.
ctx  = canvas.getContext('2d');
ctx.strokeStyle = "rgba(255,0,0,1)";
ctx.lineWidth   = 5;
ctx.lineCap     = 'round';
The context is now set up using the color red with a 5 pixel wide stroke and rounded ends. You can change these values as you like of course.

In order for our fingers to be able to produce wonderful line drawings, we need to tell our application to listen for touch events. We'll need three of them. The «touchstart» event is where we set our starting position for the drawing operation. This event fires when a finger is added to the screen. The «touchmove» is where we draw the lines, this event fires when we move a finger on the screen. The «touchcancel» is where we handle exceptions, like what happens if you receive a call in the middle of your art creation extravaganza. This event fires whenever it needs to.
canvas.addEventListener("touchstart",touchstartHandler,false);
canvas.addEventListener("touchmove", touchmoveHandler,false);
canvas.addEventListener("touchcancel", touchcancelHandler,false);

Now we'll need to handle those events as well, here is where the real fun begins! Let's have a look a the «touchstart» handler first.
function touchstartHandler(event)
{
   ctx.moveTo(event.touches[0].pageX, event.touches[0].pageY);
}
It's just one line, but do take notice in the «touches» object contained within the event. This is an array (well, kind of) of touches. The reason for this is that most humans have more than one finger, so the «touches» object could actually contain several values. We only need one, so we refer to the first (0) element in the «touches» object. Now that we have found the first finger we get it's location on the screen by asking for the «pageX/Y» values. We then continue to move the canvas context pointer to the coordinates for this finger using the «moveTo» method. This happens every time we place a finger on the screen. But, only for the first finger.
function touchmoveHandler(event)
{
    ctx.lineTo(event.touches[0].pageX, event.touches[0].pageY);
    ctx.stroke();
}
In the «thouchmove» handler we do the actual work of telling the canvas context to draw a line from where it's last location was to where the finger is now. The first time this is called the line is drawn from where we placed the finger on to the screen, set in the «touchstart» handler. After that, the canvas context will update it's starting position to the location of the last drawing operation. Like the «moveTo» command in «touchstart» the «lineTo» will update the coordinate position, but it will also issue a drawing command which is rendered to the screen when we call the «stroke» method.

That's it. Try it out on your iPad, iPhone or any other touch device which understands the new HTML 5 APIs by clicking this magical link.

Recommended further reading:

Quicktip: Flipping an image with JavaScript


Let's say you wanted to flip an image in you web-app horizontally or vertically. By using a tiny bit of JavaScript and CSS 3 this is really easy.

//Get the image
var img = document.getElementById('myimage');
//Flip it horizontally
img.style.webkitTransform = 'scaleX(-1)';


And you're done! Note that this will only work in webkit browsers. The equivalent for Mozilla browsers would be «img.style.MozTransform». To flip the image vertically you could use: «scaleY(-1)». And to flip both horizontally and vertically at the same time: «scale(-1,-1)».

[edit 17.03.2011]
You can of course do this in other browsers besides Gecko or WebKit based browsers, as pointed out in the comments. Safari will actually support both the «webkit» and the «Moz» prefix, but this will most likely go away soon. So what you'll need to use is feature detection. This will still not work in ALL browsers, but the usable ones will most likely support it.
if(img.style.webkitTransform){
  img.style.webkitTransform = 'scaleX(-1)';
}else if(img.style.MozTransform){
  img.style.MozTransform = 'scaleX(-1)';
}else if(img.style.OTransform){
   img.style.OTransform = 'scaleX(-1)';
}else if(img.style.msTransform){
   img.style.msTransform = 'scaleX(-1)';
}else{
   img.style.transform = 'scaleX(-1)';
}

HTML 5 Offline data storage

One of the most anticipated features of HTML 5 and all it's consequential technologies and APIs are the «offline storage» APIs. In this post I'll take a "real world" approach to using the HTML 5 Web-Database and the «HTML 5 Offline application cache». I will take you through an example where a complete elephant gets stored on your computer. That's right! A pink one as well! The point of this demo is to investigate how to store both static data as well as dynamic data which might not be known at design time. For this occasion I have created a demo which you are free to download and inspect. It is fully commented and somewhat verbose for easier reading. What this application does in essence is to store a HTML and a JavaScript file on your computer, then it will go on to store a picture (which could be dynamic data) in a local database, hence making the application usable when not online. Let's have a look!

So, our goal is to store both static data and some dynamic data. To achieve this we'll need to use two approaches as mentioned above. The first one, called «HTML 5 Offline Application Storage» is almost automatic once you have it configured. We will utilize this method to store our main JavaScript file so that it will work when you're not online. Cool!
This approach uses a simple text file, called a «manifest file» which tells the browser which data to store locally. In order for this file to be interpreted by the browser correctly you'll need to (1) configure your web-server to serve this file with the «text/cache-manifest» mime-type. It doesn't matter what kind of extension you use, but I prefer either «.manifest» or «.cache». Now that thats out of the way we need to create the «manifest file». Mine looks something like this.

CACHE MANIFEST
# Cache manifest version 1.0.5
# If you change the version number in this comment,
# the cache manifest is no longer byte-for-byte
# identical.

main.js

NETWORK:
# All URLs that start with the following lines
# are whitelisted.

http://web.kinderas.com/

The first line MUST be the text «CACHE MANIFEST». After that you'll go on to specify the files you'll like to be cached. Here you'll put stuff like JavaScript files, HTML pages, CSS files and so on. Mine only has the one «main.js». Note that you do NOT need to specify the HTML file which declares the manifest file. This will typically be your «index.html» file or something like that. More on that later. The next section is the «NETWORK:» section. In this section you specify a "white list" containing URL's from where your application is allowed to get it's data. If you don't specify this your app will not download any data, not from the server it's hosted on or from anywhere else. I have specified my own domain since this is where the elephant is hosted.
You declare the manifest file in your HTML file like so:
<html manifest="cache.manifest">
That is it for the manifest file actually. If you are simply going to host a static site, a game or something like that, this will work just file as is. Note that to update your files, you do need to make a change in the manifest file itself, like incrementing the version number.

Next we need to add some sexy JavaScript in order to make the pink elephant available for your viewing pleasure in locations the WiFi gods have forsaken. There are three main steps to this: (1) Opening and creating the database and the table if it's not already present. (2) Reading the image from the database or saving it to the database if it's not already in there. (3) Displaying the image. I will not be explaining every line of the code in this post, you'd rather take a look at the JavaScript file and read the comments. However I will discuss some of the more important points briefly.
Not all browsers will support the HTML 5 database APIs, so we need to check for this before we can do anything. To do this we check for the existence of the «openDatabase» method on the «window» object, like so:

if(!window.openDatabase){
// No support for HTML 5 db
return;
}

This will detect if the browser has support for the methods we need. If not, give the user a message or some alternative content.
Then, to open / create the database we would we simply write:
db = openDatabase('testdb','1.0','Offline Elephant DB',1024*1024);
We have just created a 1MB database or opened one if it already existed. Now it's ready to execute SQL queries using transactions.

var sql = 'CREATE TABLE IF NOT EXISTS offline_image (id INTEGER ....);';
db.transaction(
 function(transaction){
  transaction.executeSql(sql,[],
  function(transaction, result){
   //The table was created
  },
  errorHandler);
 }
);

The database table has now been created if it wasn't already there. We now need to check if there is an image already saved in the database, this happens on line 56 in the «readImage()» function. If there is an image with the matching filename saved, we use that, if not we go on to loading and serializing the image, as follows.

var canvas = document.createElement('canvas');
var ctx    = canvas.getContext('2d');
var img    = document.createElement('img'); 
img.onload = function(){
 canvas.width  = img.width;
 canvas.height = img.height;
 ctx.drawImage(img,0,0,img.width,img.height);
 var base64Image = canvas.toDataURL();
 showImage(base64Image);  
}
img.src = sImgURL;

To be able to save the image we need to create a text version of it's data. We can accomplish this by loading the image and then rendering it in a canvas element. The Canvas element has a method called «toDataURL» which will create a base64 representation of the Canvas content. Base64 images, also referred to as data urls can easily be saved to the database. Base64 data can also be read directly by the «img» element, so there is no need to decode the base64 string again once it's encoded. But, do note that the canvas element will give you the png base64 version of the image, and it's quite a bit larger than the original binary file.

That's the gist of it, but you do need to take a look at the demo and the JavaScript in order to really understand what it going on here. Once you get the hang of it, this is a really powerful approach to making web-applications much more accessible and more interesting.

Further reading:

9 things I've learned about web-development

I've been a developer for quite some time now, meddling with both the web-centric and the native side of things. As of lately, that is for the last 3 months or so I have focused more in depth on "standards" based web development. Meaning HTML, CSS and JavaScript. Even if I've been writing HTML since 1996 (yeah, I'm getting old), I have never really bothered to really focus in depth on the basic building blocks of HTML, CSS and JavaScript, until now. 4 books and many many hours of training videos later I feel that I've learned something, which is that an iPad make for a lousy pillow if you keep trying to sleep on it! But more than that, I found 9 things that I have learned, which may be blatantly obvious to you if you are a fancy pantsy web-developer, but then again, maybe you'll learn something new?

1. Web-designers and web-developers think differently.
What do I mean by that? Consider of how you're tagging your HTML with classes and id's. The designer approach to this would be classes all the way, then using the clever selector syntax of CSS to reach the nested areas of the document. This makes sense when working with formatting. Developers tend to view the HTML as a framework with components. Classes are used for formatting while id's are used to identify areas of the markup one would need to reach via JavaScript. Designers will prioritize the "flow" of the «document» whilst developers don't consider it a document at all. I don't think either approach is «correct» or «wrong», it's just two ways of approaching the same challenge.

2. CSS is not a layout language.
Almost all layout in modern HTML based webpages are done using CSS, so how can anybody claim that it's not a layout language? I too was somewhat surprised when time and time again the "people who knew what they are talking about" kept repeating this. From the WHATWG to W3C and several books on the topic kept driving this home..«not a layout language». Turns out, CSS is a formatting language with some layout features. Semantics? Well, not really. If you compare CSS 2.1 to a "real" layout language like MXML you'll soon notice a big difference. Layout languages, or UI markup languages have special layout components to group element, flow elements, sort elements both horizontally and vertically. CSS 2.1 does not have this, it's totally reliant on either floats or absolute positioning. This will better with the introduction of the flexible box model in CSS3, but still it will remain a formatting language at heart.

3. CSS selectors are incredible powerful...stuff
This is one of the areas on which I have discovered most new stuff. CSS 2.1 embodies most of them, but with the introduction of the CSS 3 standard, selectors can now do some amazing stuff. Conditional child selection, substrings within attributes while traversing child elements are just some examples. And the best part is that they are largely supported in all modern browsers, including Internet Explorer 8. If I where to recommend one area on with to focus you attention, if you don't already know this, it would be CSS selectors. It's not complicated or hard to understand, there are just so much under the hood which can make your CSS writing a lot more enjoyable.

4. Things will look different in different places.
If you try to create pixel perfect designs across all browsers and platforms you will go bonkers, that is unless you are a technophile machochist whom derives enjoyment from banging your head up against the gigantic wall of Internet Explorer inconsistency. You're much better off using either the progressive enhancement or the graceful degradation approach where you serve different users the same content, only wrapped in a slightly different presentation. This way Internet Explorer users can sit and stare at that black and white page of rich text all day long, while us WebKit fanboys can swim in the loveliness that is a modern browser with animations and shit.

5. A position is not the same position elsewhere, or everywhere.
Since this is more or less an extension of point 4, I can't be bothered to find a pretty picture for this one. (As a side note, if you use Google image search for the term "position", turn safe search on!) What this point is concerning, what I've found is: Firefox and Chrome (or any other browsers) does not have the same interpretation when it comes to rendering a point at, say x: 100, y: 100. Since it's up to the user agent (browser) to parse your CSS and HTML and then draw it on the screen, you will at certain points end up in a situation where an absolute point in the top left coordinate system will differ from user agent to user agent and even on the same user agent on different operating systems. This can be avoided by using floats and containers instead of using absolute positioning. But, it's better to accept that things might not look exactly the same everywhere.

6. Modernizer Rocks!
If you ever need to use conditional CSS 3 or HTML 5, Modernizer is by far the best solution I've found. The way Modernizer works is actually twofold. You can first use it with CSS directly. Lets say you want to take advantage of the RGBA color model found in CSS 3, but you also need to support those pesky Internet Explorer users. All you need to do in your stylesheet is to prefix your class or id selector with ".rgba". Let's say I wanted to apply a style via the selector «h2[class*="onkey"]», but only for browsers supporting RGBA. It would look like this: «.rgba h2[class*="onkey"]». The RGBA class simply adds itself as a ascendant class. This style would then only apply if RGBA was supported. The other way of using Modernizer is with JavaScript. To check for support for H.264 video playback abilities, simply use «Modernizer.video.h264» and it'll return false, "maybe" or "probably". Yep, that is the HTML 5 spec for video format detection..

7. jQuery selectors are convenient, JavaScript is fast!
If you don't know what jQuery is, you should go find out! Someone once wrote that jQuery is Gods gift to JavaScript. Where God is of course John Resig and I was the one that wrote that, just now in fact. jQuery is seriously awesome, it allows for fast and easy cross browser development. Underscoring cross browser, which is what it does really really well. It is just a JavaScript framework, a tiny one at that, but crammed with neat functionality, from animations, ajax loading and the usage of CSS selectors to get a hold of DOM elements. You can say things like: «jQuery('div.donkey')» which would give you all the donkey divs in the page. This is really convenient, because you can find stuff in the DOM with the same syntax used in the CSS. There is a downside however. When using CSS selectors in a CSS file or in the HTML file, the user agent takes care of all the heavy lifting required to traverse the DOM and find those elements. This is fast because the user agent does this natively using a compiled language such as C. However, jQuery is not written into the native part of the browser and will therefore need to use JavaScript to traverse the DOM to find the elements based on the CSS selector. Hence using the build in JavaScript functions «getElementById», «getElementsByTagName» or the spanking new «getElementsByClassName» is much faster than using the jQuery selectors. What you can do is combine them like so «jQuery(getElementById('id-name'))». Then you would get the speed of the native JavaScript functions while keeping all the jQuery goodness as well.

8. There are datatypes in JavaScript!
!!Nerd alert!! Even if you don't explicitly declare datatypes in JS, there is a difference between for example «"2"» and «2». If you where to add these two values together «"2" + 2», you'd get «"22"», while «2 + 2» returns «4». Now, what if «a = [2,3,"a"]» and «b = 2». What would «a + b» give you? That's right «a + b => "2,3,a2"». JS has a lot of functions for dealing with this. You have «toString()» to convert a number to a string, «parseInt(strNum)» to convert a string into a whole number and so on. The important thing is to be astutely aware of it, even if you can't declare a strict datatype.

9. The WebKit Web Inspector is your most important tool
If you're in any WebKit browser, Safari, Chrome so on you have access to the build in "Web Inspector". This tool is your best friend when working with HTML, CSS and JavaScript. It will do anything the more famous Firebug does and more. Don't get me wrong, I'm not railing on Firebug which is an awesome tool, I am however highly recommending the WebKit Web Inspector because of it's speed, advanced profiling tools and unsurpassed JavaScript debugger. Try it and you'll see why I'm praising it!

So that's it, or more likely, that's some of it. If you have actually read all the text down to this I truly hope that this post have contributed in some small way to your blah blah blah blah..you know the drill. Now get back to work, those recursive functions won't be creating themselves ;-)

Scrolling a div on multitouch devices using JavaScript

With the emergence of touch devices and the slow but steady tendency of replacing the mouse as an input device, this leaves us with fingers. Both the iOS platform and the Android platform sports APIs for dealing with touches from fingers, for native apps that is. But what about web-apps? Enter the JavaScript touch DOM events. In this post I'll discuss how to use the touch events to scroll a container (a div) using a finger, e.g. on an iPhone.

What you'll need
First of all you need a touch device or a simulator like the iPhone simulator to test your code. The code itself can be written in any text editor, however it is recommended to use an editor with a build in debugger or a test environment that supports debugging JavaScript touch events. You might be thinking that Firebug or Drosera is great for debugging, but how exactly would you trigger the touch events in your desktop browser? Well, you can't. This is why I'm using Dashcode from the iOS SDK for my JavaScript coding. More on using Dashcode in a later post.
Note that this code is written for WebKit based browsers, but should work in principle on other touch browsers as well.

The HTML
<div id="holder">
   <div class="content">
       your content here
   </div>
</div>


Notice that the content is inside of a div within the holder div, this is because you can't scroll the div in which the touch event is attached to.

The CSS

#holder{
   width: 300px;
   height: 200px;
   background-color: blue;
   -webkit-box-shadow: 3px 3px 5px #000;
   padding: 10px;
}

#holder div{
    width:100%;
    height:100%;
    color: white;
    overflow: auto;
    -webkit-user-select: none;
}


Not much revolutionary here, but do note that we set the "overflow" property to auto on the content div, not the holder itself. Also, we set the "-webkit-user-select" to "none" on the content div, thereby preventing the user of selecting the content. This is optional.

The JavaScript
There are three main touch events:
  • touchstart - Called when a finger touches the listening container (finger down)
  • touchmove - Called repeatedly when a finger moves (finger down and moving)
  • touchend - Called when a finger leaves the listening container (finger up)
Each of these methods gives us an event with a touches array. Remember, there might be more than one finger since these APIs are made to handle multitouch devices. To get a hold of the vertical position of one finger you would query the touches array for one finger and get it's pageY property, like this: event.touches[0].pageY

From this we can calculate and set the scrollTop property of the content container. But, wait! If you try this the rest of the page will also scroll, not what we wanted. The reason why this happens is because the touch event bubbles all the way up to the window, making the browser think it needs to scroll the window because you have dragged your finger on it. We need to tell the event to stop bubbling, we will handle the event ourselves. We do this by calling: event.preventDefault()

The complete JavaScript code will then look something like this:

var startPos;
function init()
{
    var scrollArea = document.getElementById('holder');
    scrollArea.addEventListener('touchstart', function(event){
        touchstartHandler(event);
    }, false);

    scrollArea.addEventListener('touchmove', function(event){
        touchmoveHandler(event);
    }, false);

    scrollArea.addEventListener('touchend', function(event){
        touchendHandler(event);
    }, false);
}

function touchstartHandler(e)
{
    startPos = e.touches[0].pageY;
}

function touchmoveHandler(e)
{
    var touch = e.touches[0];
    var targetBox = e.currentTarget.getElementsByTagName("div")[0];
    e.preventDefault();

    var fingerMoved = startPos - touch.pageY;
    startPos = touch.pageY;

   targetBox.scrollTop = targetBox.scrollTop + fingerMoved;

}

This is just a simple example, but it's something you'll probably end up using a lot. Speaking of...

When should you override the default window scroll
On an iPhone there is not as much need for this method as you'll probably scroll the entire screen in most cases anyway. However, the iPad is a different story. Take a look at the iPad version of gMail created by Google. They are using this method with success, and they have added inertia scrolling as well. This can be accomplished using the last touch event we did not implement, touchend. Maybe more on this in a later post. Anyway, you should use you own scrolling when it's appropriate to scroll only a part of the app, like a spilt view list or something like that.