Spot the web RSS 2.0
# Monday, February 25, 2008

At a fundamental level it's important to understand how JavaScript timers work. Often times they behave unintuitively because of the single thread which they are in. Let's start by examining the three functions that we have access to with which to construct and manipulate timers.

  • var id = setTimeout(fn, delay); - Initiates a single timer which will call the specified function after the delay. The function returns a unique ID with which the timer can be canceled at a later time.
  • var id = setInterval(fn, delay); - Similar to setTimeout but continually calls the function (with a delay every time) until it is canceled.
  • clearInterval(id); - Accepts a timer ID (returned by either of the aforementioned functions) and stops the timer callback from occurring.

In order to understand how the timers work internally there's one important concept that needs to be explored: timer delay is not guaranteed. Since all JavaScript in a browser executes on a single thread asynchronous events (such as mouse clicks and timers) are only run when there's been an opening in the execution. This is best demonstrated with a diagram, like in the following:


(Click to view full size diagram)

There's a lot of information in this figure to digest but understanding it completely will give you a better realization of how asynchronous JavaScript execution works. This diagram is one dimensional: vertically we have the (wall clock) time, in milliseconds. The blue boxes represent portions of JavaScript being executed. For example the first block of JavaScript executes for approximately 18ms, the mouse click block for approximately 11ms, and so on.

Since JavaScript can only ever execute one piece of code at a time (due to its single-threaded nature) each of these blocks of code are "blocking" the progress of other asynchronous events. This means that when an asynchronous event occurs (like a mouse click, a timer firing, or an XMLHttpRequest completing) it gets queued up to be executed later (how this queueing actually occurs surely varies from browser-to-browser, so consider this to be a simplification).

To start with, within the first block of JavaScript, two timers are initiated: a 10ms setTimeout and a 10ms setInterval. Due to where and when the timer was started it actually fires before we actually complete the first block of code. Note, however, that it does not execute immediately (it is incapable of doing that, because of the threading). Instead that delayed function is queued in order to be executed at the next available moment.

Additionally, within this first JavaScript block we see a mouse click occur. The JavaScript callbacks associated with this asynchronous event (we never know when a user may perform an action, thus it's consider to be asynchronous) are unable to be executed immediately thus, like the initial timer, it is queued to be executed later.

After the initial block of JavaScript finishes executing the browser immediately asks the question: What is waiting to be executed? In this case both a mouse click handler and a timer callback are waiting. The browser then picks one (the mouse click callback) and executes it immediately. The timer will wait until the next possible time, in order to execute.

Note that while mouse click handler is executing the first interval callback executes. As with the timer its handler is queued for later execution. However, note that when the interval is fired again (when the timer handler is executing) this time that handler execution is dropped. If you were to queue up all interval callbacks when a large block of code is executing the result would be a bunch of intervals executing with no delay between them, upon completion. Instead browsers tend to simply wait until no more interval handlers are queued (for the interval in question) before queuing more.

We can, in fact, see that this is the case when a third interval callback fires while the interval, itself, is executing. This shows us an important fact: Intervals don't care about what is currently executing, they will queue indiscriminately, even if it means that the time between callbacks will be sacrificed.

Finally, after the second interval callback is finished executing, we can see that there's nothing left for the JavaScript engine to execute. This means that the browser now waits for a new asynchronous event to occur. We get this at the 50ms mark when the interval fires again. This time, however, there is nothing blocking its execution, so it fires immediately.

Let's take a look at an example to better illustrate the differences between setTimeout and setInterval.

  setTimeout(function(){
    /* Some long block of code... */
    setTimeout(arguments.callee, 10);
  }, 10);
 
  setInterval(function(){
    /* Some long block of code... */
  }, 10);

These two pieces of code may appear to be functionally equivalent, at first glance, but they are not. Notably the setTimeout code will always have at least a 10ms delay after the previous callback execution (it may end up being more, but never less) whereas the setInterval will attempt to execute a callback every 10ms regardless of when the last callback was executed.

There's a lot that we've learned here, let's recap:

  • JavaScript engines only have a single thread, forcing asynchronous events to queue waiting for execution.
  • setTimeout and setInterval are fundamentally different in how they execute asynchronous code.
  • If a timer is blocked from immediately executing it will be delayed until the next possible point of execution (which will be longer than the desired delay).
  • Intervals may execute back-to-back with no delay if they take long enough to execute (longer than the specified delay).

All of this is incredibly important knowledge to build off of. Knowing how a JavaScript engine works, especially with the large number of asynchronous events that typically occur, makes for a great foundation when building an advanced piece of application code.

Monday, February 25, 2008 5:01:18 PM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
Javascript | Programming
# Tuesday, February 19, 2008

In this tutorial, i will be teaching you how to create a mini javascript framework. Now its not going to be anywere near as feature rich as other frameworks such as mootools and jquery but its a start.



Step 1 : Create the files

index.htm, Our html file
framework.js, Our javascript file



Step 2 : Populate the index.htm file

Ok first things first, lets get some html code into our index file.

Code
GeSHi (html4strict):
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml">
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  5. <title>Framework</title>
  6.  
  7. </head>
  8.  
  9.  
  10. </body>
  11. </html>
  12.  
Created by GeSHI 1.0.7.20


The above code is pretty self explanatory.

Now, add the link to our javascript file inbetween the head tags

Code
GeSHi (html4strict):
  1. <script type="text/javascript" src="framework.js"></script>
Created by GeSHI 1.0.7.20


Next thing to do, add some functions from the frame work we will create. Add this after the first script tags

Code
GeSHi (html4strict):
  1. <script type="text/javascript">
  2. <!--
  3. window.onload = function() {
  4.  
  5. Framework.Effects.add("box", 'blink', function() {
  6.    // Functions here
  7. });
  8.  
  9. Framework.Effects.start();
  10.  
  11. }
  12. //-->
  13. </script>
Created by GeSHI 1.0.7.20


Explanation of the above:

window.onload = function() { }
This tells the browser to run the code inside the function after the page has fully loaded.

Framework.Effects.add("box", 'blink', function() {
   // Functions here
});

This is a function that we will create. It has three parameters, object id, effect type and function.
The first parameter should be a string of the id for the object we want to put the effect on.
The second parameter is the effect type. For this tutorial, there will only be one effect, "blink".
The third and final parameter is the function. Here you put what ever code you want to run when ever the effect starts.

Framework.Effects.start();
This is another framework function that we will create. All it does is tell the browser to start the effects.



Step 3 : The framework itself

This is the longest step in the tutorial so pay attention.
In this step, open up framework.js as this is the file we will be editing.

Firstly, we have to create our framework object. Put this code at the top of the page:

Code
GeSHi (javascript):
  1. var Framework = new Object();
Created by GeSHI 1.0.7.20

This just tells the browser that the variable Framework is an object.

Next, we create our first sub-object: Styles
Put this code after the framework variable.

Code
GeSHi (javascript):
  1. Framework.Styles = {
  2. add: function(obj, styles) {
  3. for (style in styles) {
  4. obj.style[styles[style][0]] = styles[style][1];
  5. }
  6. },
  7.  
  8. rem: function(obj, styles) {
  9. for (style in styles) {
  10. obj.style[styles[style][0]] = null;
  11. }
  12. },
  13.  
  14. get: function(obj, style) {
  15. return obj.style[style];
  16. }
  17. };
Created by GeSHI 1.0.7.20


Now to explain it all.

Framework.Styles = {};
This creates the Styles object in the Framework object.

add: function(obj, styles) {
   for (style in styles) {
      obj.style[styles[style][0]] = styles[style][1];
   }
},

This is the first function in our styles object. It takes two parameters, a html object and an array.
The object is simply:
... document.getElementById('objid') ...

The array format is like so:

Code:
Array {
Array {
'styletype',
'styles'
}
}

The styletype would be a css attribute like color and the styles would be a value like #ff0000

for (style in styles) {
   obj.style[styles[style][0]] = styles[style][1];
}

This creates a simple for loop. It works in the same way as a PHP foreach loop.

PHP

Code
GeSHi (php):
  1. foreach ($styles as $style) {}
Created by GeSHI 1.0.7.20


Javascript

Code
GeSHi (javascript):
  1. for (style in styles) {}
Created by GeSHI 1.0.7.20


As you can see its almost identical.

obj.style[styles[style][0]] = styles[style][1];
This gets the objects styles and then edits the styletype with the styles.

If coding this literally, it would be:

Code:
obj.style.color = "#ff0000";


rem: function(obj, styles) {
   for (style in styles) {
      obj.style[styles[style][0]] = null;
   }
},

This does exactly the same thing except each styletype in the array is removed from the object.

get: function(obj, style) {
   return obj.style[style];
}

Byfar the simplest function in the Styles object, this just gets the object, the style specified and returns the styles contents.

Example usage:

Code:
var object = document.getElementById("box");

// Setting the styles using the previous add function
Framework.Styles.add(object, [
['color', '#ff0000']
]);

alert(Framework.Styles.get(object, 'color'));
// Will alert, you guessed it, #ff0000


The Effects Object
Now we are going to create the main effects object. This is the part the tutorial has been building up to.
Here is the beast in all its glory:

Code
GeSHi (javascript):
  1. Framework.Effects = {
  2. effects: [],
  3. timers: [],
  4.  
  5. add: function(obj, type, func) {
  6. Framework.Effects.effects.push([type, obj, func]);
  7. },
  8.  
  9. blink: function(obj, func) {
  10. var obj = document.getElementById(obj);
  11.  
  12. setInterval(function() {
  13. if (Framework.Styles.get(obj, 'visibility') == 'hidden') {
  14. Framework.Styles.add(obj, [['visibility', 'visible']]);
  15. } else {
  16. Framework.Styles.add(obj, [['visibility', 'hidden']]);
  17. }
  18.  
  19. func();
  20. }, 500);
  21. },
  22.  
  23. start: function() {
  24. for (effect in Framework.Effects.effects) {
  25. var effect = Framework.Effects.effects[effect];
  26. Framework.Effects.timers[effect[0] + effect[1]] = false;
  27.  
  28. switch (effect[0]) {
  29. case 'blink':
  30. Framework.Effects.blink(effect[1], effect[2]);
  31. break;
  32. }
  33. }
  34. }
  35. };
Created by GeSHI 1.0.7.20


Confusing huh? Well not to worry, I shall explain it all. Before I do, add that code under the Styles object.
Now lets explain it.

Framework.Effects = {};
This creates another object just like the Styles object.

effects: [],
timers: [],

These are two empty arrays. Yes, thats right, arrays. You can define arrays in two ways in javascript:
var array = new Array();
or
var array = [];
Guess which one I use.

add: function(obj, type, func) {
   Framework.Effects.effects.push([type, obj, func]);
},

Remember when we used the add function on the HTML page? Well this is the function that gets called.

Quik Recap:

Code
GeSHi (javascript):
  1. // This is what we wrote on the HTML page
  2.  
  3. Framework.Effects.add("box", 'blink', function() {
  4.   // Functions here
  5. });
Created by GeSHI 1.0.7.20


Now the first parameter is a STRING not an Object like the functions in the Styles object. There is a reason for this but I will not explain it in this tutorial.
The second parameter is the effect type. Also a string.
The third is the function. Now if left empty, nothing will run when the effect blink is run. If there is code in it, it will be run every time the blink effect is run.

Framework.Effects.effects.push([type, obj, func]);
This just pushes a new array into the effects array we defined earlier. It contains the effect type, object id and function.

blink: function(obj, func) {
   var obj = document.getElementById(obj);

   setInterval(function() {
      if (Framework.Styles.get(obj, 'visibility') == 'hidden') {
         Framework.Styles.add(obj, [['visibility', 'visible']]);
      } else {
         Framework.Styles.add(obj, [['visibility', 'hidden']]);
      }
      
      func();
   }, 500);
},

Here we go. Our first effect in the mini framework. It takes two parameters, object id and function.

var obj = document.getElementById(obj);
This creates a new variable called obj which contains the object of the id given.

setInterval(function() {
   if (Framework.Styles.get(obj, 'visibility') == 'hidden') {
      Framework.Styles.add(obj, [['visibility', 'visible']]);
   } else {
      Framework.Styles.add(obj, [['visibility', 'hidden']]);
   }
   
   func();
}, 500);

This is the most important part of our blink effect even though its very simple.
The first part is to create an interval. Some of you may know it as setTimeout. setInterval is the samething but I prefere using it. This interval is set to run at every 500 milliseconds or every half second in simple terms.

if (Framework.Styles.get(obj, 'visibility') == 'hidden') {
   Framework.Styles.add(obj, [['visibility', 'visible']]);
} else {
   Framework.Styles.add(obj, [['visibility', 'hidden']]);
}

Here we make use of some functions we created in the Styles object. The if statement uses the get function in the Styles object to check the value of the objects visibility style.
If its hidden, use the add function to make the visibility visible else make it hidden again. This will just loop over and over so you get the blink effect.

func();
Now this is the function that we put as the third parameter on the index page. Remember?

Quik Recap:

Code
GeSHi (javascript):
  1. // This is what we wrote on the HTML page
  2.  
  3. Framework.Effects.add("box", 'blink', function() {
  4.   // This is the third parameter
  5.  
  6.   // Functions here
  7. });
Created by GeSHI 1.0.7.20


Because it was passed through a variable, to run the function inside, all we have to do is put brackets at the end. Neat huh?

start: function() {
   for (effect in Framework.Effects.effects) {
      var effect = Framework.Effects.effects[effect];
      Framework.Effects.timers[effect[0] + effect[1]] = false;
      
      switch (effect[0]) {
         case 'blink':
            Framework.Effects.blink(effect[1], effect[2]);
         break;
      }
   }
}

Yay, the final function in the Effects frame work. I am happy because its 2:45am and I am very tired.
Now we create a function called start. We ran it once on the index page.

Quik Recap:

Code
GeSHi (javascript):
  1. window.onload = function() {
  2.  
  3. Framework.Effects.add("box", 'blink', function(){});
  4.  
  5. // Here we go
  6. Framework.Effects.start();
  7.  
  8. }
Created by GeSHI 1.0.7.20


This function makes it all work. It goes through the effects array we looked at in the add function, gets the effect type and sends the appropriate information to the appropriate effects functions.

for (effect in Framework.Effects.effects) {
   var effect = Framework.Effects.effects[effect];
   Framework.Effects.timers[effect[0] + effect[1]] = false;
   
   switch (effect[0]) {
      case 'blink':
         Framework.Effects.blink(effect[1], effect[2]);
      break;
   }
}
Here we have another for loop. Same type as the one I explained earlier.

Quik Recap:

Code:
PHP
foreach ($styles as $style) {}

Javascript
for (style in styles) {}


This for loop gets all the effect arrays in the effects variable.
var effect = Framework.Effects.effects[effect];
The effect variable now contains this iterations array contents.

Framework.Effects.timers[effect[0] + effect[1]] = false;
Because this is not needed in this framework for this tutorial, I will not explain it. Leave it in there though as it will be needed for future parts to this tutorial.

switch (effect[0]) {
   case 'blink':
      Framework.Effects.blink(effect[1], effect[2]);
   break;
}

Here we have a simple switch statement. Works in the same way as a PHP switch statement. For those of you who dont know what a switch statement is, think of it like this:

Code:
switch (variable) {
case "a":
alert("a");
break;

case "b":
alert("b");
break;

case "c":
alert("c");
break;

default:
alert("Unknown letter");
break;
}

IS

if (variable == "a") {
alert("a");
} else if (variable == "b") {
alert("b");
} else if (variable == "c") {
alert("c");
} else {
alert("Unknown letter");
}


The switch statement simply gets the effect type and sends the object id and function to the particular effect.



And there you have it. An introduction to a simple javascript mini effects framework. I hope you have learned alot from this tutorial.

Tuesday, February 19, 2008 5:39:11 PM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
Javascript | Web 2.0
# Sunday, February 17, 2008

Six months after Facebook came out with a version of its social network for the iPhone, LinkedIn is finally coming around to releasing a mobile version of its own.

It is live now. Just go to http://m.linkedin.com/ on any mobile browser. Of course, if you have an iPhone, you will see a version optimized just for that device.

This isn’t exactly what we had in mind when we noted there is still an opportunity to create a kick-ass mobile social network.

 linkedin-iphone-small-1.png

But the basic functionality is all there. You can look up people’’s profiles, invite people into your network, and see updates from your contacts. More fully-featured, downloadable mobile apps geared to specific phones may be coming in the future.

Even limited mobile browser accessibility should help LinkedIn keep its members happy. The regular Website has been on a tear lately, nearly tripling in unique visitors over the past year in the U.S., to 3.6 million in January 2008, according to comScore.

No signs of social networking fatigue there.

linkedin-chart.png

Sunday, February 17, 2008 5:37:15 PM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
Site Reviews | Web 2.0
Navigation
Archive
<February 2008>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2012
Guy Levin
Sign In
Statistics
Total Posts: 63
This Year: 0
This Month: 0
This Week: 0
Comments: 14
Themes
All Content © 2012, Guy Levin