Put your message here! Contact me for more information
 
 







 

Archive for the ‘Tutorials’ Category


 

Based on an article on detection connection speed using JavaScript, I implemented a more completed speed detection solution which you can drop into your project with minimal fuss. An example would be to detect the user’s connection speed to show either high or low bandwidth version of the website. All the ingredients you need are an image, a small JavaScript snippet, and some imagination. There is no dependency and no other 3rd party library needed.

The main idea is that we load an image programmatically and measure the time it takes the browser to load such an file. Once an image is done loading, the browser will fire the onLoad event and we can capture the end time. I included two different versions of the code. The first one is quite simple with the image being loaded only once. The second one is more sophisticated, loading the image multiple times and taking the average loading time to arrive at a more accurate answer.

The key technique being used here are closure and passing functions as arguments. These two techniques are very commonly used in modern JavaScript frameworks such as Prototype, Scriptaculous, jQuery, Ext, YUI, etc.

In order for this technique to work, we need to have an image with an average size. Too small of an image won’t give us a very good result while too big of an image will cause more lags and affect the user’s experience. For your convenience, I included the a JPG image around 58.5KB in size as our testing image. We will need the exact size of the image in Bytes in order to calculate the bitrates or byte-rates.

Simple Javascript Speed Detection
Insert this code snippet into the page where you want to conduct the speed test

var SpeedTest = function() {
  /*
  From:  http://techallica.com/kilo-bytes-per-second-vs-kilo-bits-per-second-kbps-vs-kbps/
  256 kbps            31.3 KBps
  384 kbps            46.9 KBps
  512 kbps            62.5 KBps
  768 kbps            93.8 KBps
  1 mbps ~ 1000kbps   122.1 KBps
  */
};
SpeedTest.prototype = {
  imgUrl: "speedtest.jpg"    // Where the image is located at
  ,size: 59917                // bytes
  ,run: function( options ) {

    if( options && options.onStart )
      options.onStart();

    var imgUrl = this.imgUrl + "?r=" + Math.random();
    this.startTime = (new Date()).getTime() ;

    var testImage = new Image();
    var me = this;
    testImage.onload = function() {
      me.endTime = (new Date()).getTime();
      me.runTime = me.endTime - me.startTime;

      if( options && options.onEnd )
        options.onEnd( me.getResults() );
    };
    testImage.src = imgUrl;
  }

  ,getResults: function() {
    if( !this.runTime )
      return null;

    return {
      runTime: this.runTime
      ,Kbps: ( this.size * 8 / 1024 / ( this.runTime / 1000 ) )
      ,KBps: ( this.size / 1024 / ( this.runTime / 1000 ) )
    };
  }
}

First, we need to specify where we would load the image from (in this case, the relative path to the page) and the exact size of that image in Kilobytes. Since we don’t want the browser to cache the image, which short-circuits our test, we append a random number to the original image’s url (line 19). Before we run the test, we check to see if we need to run the onStart() functions being passed in. The idea is that you can show on the page with some messages or pop-up to notify about the test is about to run, simply by passing in an inline function.

The crux of the detection is from line 23 to line 30. If you are new to JavaScript or you are not comfortable with Closure, you should investigate a bit more since Closure is a critical and extremely powerful part of Object-Oriented JavaScript. In its simplest form of explanation, Closure means an anonymous function from a different execution context can gain access to another function’s internal properties.

In this case, after downloading the image, the browser fires the image’s onLoad event at a later time in a different execution context (the context of the current browser) other than context of our SpeedTest object. Without a closure reference via the variable “me” (line 23), which holds the reference to the SpeedTest object, we can no longer access to the startTime and endTime properties of the current SpeedTest object.

Now to run the test and obtain the results, all you have to do is to initialize a new SpeedTest object, execute the run() method, and pass in your custom actions. Currently 2 custom events onStart() and onEnd() are supported:

var st = new SpeedTest();
st.run({
  onStart: function() {
    alert('Before Running Speed Test');
  }

  ,onEnd: function(speed) {
    alert( 'Speed test complete:  ' + speed.Kbps + ' Kbps');
    // put your logic here
    if( speed.Kbps < 200 )
    {
      alert('Your connection is too slow');
    }
  }
});

The Multi-trial speed test

As with any kind of measurements, one single measure is subjected to certain errors and inaccuracy. In our case, the degree of inaccuracy is much higher since connection speed fluctuates constantly. Other factors would affect the single-pass test is the initial DNS look-up speed and overhead, temporal network latency, slow browser, etc. Hence we can further improve our answers by taking multiple tests and average the results to get a more accurate number.

Below is a more sophisticated speed-detection code, which we can specify how many times the test is run. Typically 3 runs is good enough and it will not impact on the user’s experience.

var SpeedTest = function() {
  /*
  From:  http://techallica.com/kilo-bytes-per-second-vs-kilo-bits-per-second-kbps-vs-kbps/
  256 kbps            31.3 KBps
  384 kbps            46.9 KBps
  512 kbps            62.5 KBps
  768 kbps            93.8 KBps
  1 mbps ~ 1000kbps   122.1 KBps
  */
};
SpeedTest.prototype = {
  runCount: 3                 // how many times we want to run the test for
  ,imgUrl: "speedtest.jpg"    // Where the image is located at
  ,size: 59917                // bytes
  ,run: function( options ) {
    this.results = []; // reset the results
    this.callback = ( options && options.onEnd ) ? options.onEnd : null;
    this.runTrial(0, options);
  }

  ,runTrial: function(i, options ) {
    var imgUrl = this.imgUrl + "?r=" + Math.random();
    var me = this;
    var testImage = new Image();
    testImage.onload = function() {
      me.results[i].endTime = ( new Date() ).getTime();
      me.results[i].runTime = me.results[i].endTime - me.results[i].startTime;

      if ( i < me.runCount - 1 )
        me.runTrial( i + 1 ); // run the next trial
      else
      {
        // Execute the callback
        if( me.callback )
          me.callback( me.getResults() );
      }
    };
    this.results[i] = { startTime: ( new Date() ).getTime() };
    testImage.src = imgUrl;
  }

  ,getResults: function() {
    var totalRunTime = 0;
    for( var i = 0; i < this.runCount; i++ )
    {
      if( !this.results || !this.results[i].endTime )
        return null; // exit if we found no endTime.  --> test’s not done yet
      else
        totalRunTime += this.results[i].runTime;
    }

    var avgRunTime = totalRunTime / this.runCount;

    return {
      avgRunTime: avgRunTime
      ,Kbps: ( this.size * 8 / 1024 / ( avgRunTime / 1000 ) )
      ,KBps: ( this.size / 1024 / ( avgRunTime / 1000 ) )
    };
  }
}

Even though our test method has changed, you can still use the same exact code as above to run the speed-test. The answer will be much more accurate this time. Basically we run multiple trials back-to-back, each time measuring the runtime and store it into an array, then average and get the final result.

Another small difference is that we have to store the reference to the user’s custom onEnd() method as a property of the SpeedTest object so that at the end of the test, we can execute it and return the answer to the user.

Final words

I hope you enjoy this article and make good use of the code. I packaged the 2 versions and the image into a zip file so just go ahead and have some fun. Go speed-racer!

Download

view comments
 

I was implementing an Ajax feature for a project and felt the need to display messages (progressing, savings prompt, etc.) to the users visibly and unobtrusively. Usually, to indicate a background activity, I tend to hide the link/button/checkbox and show a spinning indicator when the Ajax request was created, then return the link when the request has completed. In this case, there is no user-controllable submit button. It is a photo album page which allows users to rearrange their photos by simply dragging-and-dropping the photos into the correct positions. The positions are saved automatically on the fly. If I am to implement a typical spinning indicator, I have to make sure that it is visible enough for the user to know that the positions are being saved. However, if the user is at mid-page, any indicator at the top section of the page won’t be visible. If I place the indicator at the bottom of the page, I still run into the same situation. My solution is to implement a smart “Prompt” bar that stays affixed to the screen. With Prototype and Scriptaculous, implementation is a breeze.

Show, don’t just tell
Here is a demo which you can try out.

Details
This is made possible by using the “position:fixed” feature of CSS. According to W3Schools,

position: fixed
An element with position: fixed is positioned at the specified coordinates relative to the browser window. The element’s position is specified with the “left”, “top”, “right”, and “bottom” properties. The element remains at that position regardless of scrolling. Works in IE7 (strict mode)

The markup
Here is the HTML for the prompt bar. You can place this HTML anywhere in the page. Ideally it should be outside any container.

Some Prompt Here
Cross

CSS

#prompt
{ position: fixed; width: 400px; height: 20px; border: 1px solid #7F7F7F;z-index: 9999; background-color: #F3FF8F; }

#prompt_message
{ float: left; text-align: center; width: 380px; font-weight: bold;}
#prompt_close
{ float: right; width:16px;}

We have to set the prompt bar’s position to be fixed so that it will stay in place when we scroll the browser window.

The script
The javascript code is fairly simple, since Prototype and Scriptaculous already do the all the heavy lifting (e.g. positioning, animation). The only catch with position:fixed div is that we cannot center the prompt div using CSS. We have to explicitly set the left coordinate before we display the bar (line 16, _center() method). This is to also useful when the user resizes the browser window, we recalculate the position and center the div accordingly.

    var Prompt = {
      autoHideTime: 5000

      ,display: function( msg, options ) {
        $('prompt_message').innerHTML = msg;
        Prompt.show();
        if( options && options.autoHide )
          setTimeout('Prompt.hide()', options.autoHideTime || Prompt.autoHideTime );
      }

      ,working: function(msg, options) {
        msg = '  ’ + msg;
        Prompt.display( msg, options );
      }

      , _center: function(){
        $(’prompt’).style.left = ( ( document.viewport.getWidth() - parseInt( $(’prompt’).offsetWidth ) ) / 2 ) + ‘px’ ;
      }

      ,show: function(){
        Prompt._center();
        new Effect.Move ($(’prompt’),{ x: parseInt( $(’prompt’).style.left ), y: 0, mode: ‘absolute’, duration: 0.2 });
      }
      ,hide: function( msg) {
        new Effect.Move ($(’prompt’),{ x: parseInt( $(’prompt’).style.left ), y: -30, mode: ‘absolute’, duration: 0.1 });
      }
    }

Since the code is simple enough, I’d like to leave the details to you to work out.

Enjoy!

Download

I packaged the demo as a zip file so you can grab it and have some fun. Cheers!

view comments
 

AutoHotKeyI guess my relationship with the Lenovo 3000 N100 laptop is a complicated one: as much as I hated the Home/End/Page up/Page down combo madness, I truely missed that 2 extra buttons that my Dell D830 doesn’t have. Now instead of just flicking my finger to hit Home or End, I have to move my entire arm to reach for either End or Home. Even though now I won’t make any mistakes with Home/End jumping as with the Lenovo, I have to slow down the typing with the Dell…. NO! Only if Dell put the 2 extra home/end button next to their Arrow buttons… Why can’t we just live happily with each other? Is it really that hard to design a good working keyboard, or is it me that just being picky about laptop keyboard?

“Good news everyone…”, as the Professor Farnsworth would say in his quite-mischevious voice, I have the fix for my crave for the Home/End buttons. AutoHotKey allows me to map custom shortcut to the keyboard, especially the Windows key. I mostly use the Windows key as the … boss key to quickly hide my stuff on the screen (Window + D), or run command (Window + R), or start Explorer (Window + E), even though these days I prefer xplorer2. With AutoHotKey, I was able to map Window + A to the Home Button, and Window + S to the End button, saving me from wiggling my arm around.

So if you are not satisfied with your laptop keyboard, give AutoHotKey a try. Maybe it will save you some aggravation.

Here is the small script to remap your Home and End button: AutoHotKey.ahk

view comments
 

Dell Latitude D830 I had to order a new replacement for my new Dell Latitude D830. I thought that there was something wrong with my particular D830’s battery compartment since there is a gap between the memory and the rest of the laptop body. I have a 9-Cell battery and it was not fully tight-fit. The gap wasn’t that big but I could actually wiggle the battery and had it making some clicking noise. So I had Dell send me a new replacement. An exact D830 was sent to me. It’s so exact that the same issue happens, again! 2 brand new D830, same wiggling battery compartment! Anyhow, I think I just live with it since I can fix the issue by putting a small peace of folded paper between the battery and the compartment wall to nudge-fit it. I think that the issue is specific to the 9-Cell battery and the D830. Buyer beware!

SystemRescueCDEnough of my rant. I actually want to talk how I transfered the image of the first D830 to the other one using the SystemRescueCD. SystemRescueCD is a Linux-bootable image that contains all the utilities for disk imaging, partitioning, and other utilities. The ISO is about 160MB. All I had to do was burning it to a blank CD and grabbing my external USB drive to store my image files.

While waiting for my replacement D830, I installed everything I want to the “defective” laptop: Launchy, FireFox, Office, VisualStudio 2005, Rails, e-texteditor, Notepadd++, Cropper, FileZilla, Xplorer2, Xampp, Cygwin, MySQL GUI toolkit, etc.. Everything was about 10GB of data.

I booted the laptop using the SystemRescue CD with my 500GB Seagate FreeAgent external USB Drive (man, I feel like I’m doing free-advertisements now). The linux distro booted up and successfully recognized my USB drive. Next I went into the GUI with startx since I’m not too hot about the command line, plus I can have multiple XTerm’s side-by-side in X. Now it’s time to get down to the cloning business.

Mounting and Imaging the external USB drive

  • First of all, my Seagate FreeAgent drive was NTFS-formatted by the manufacture. Secondly, I wasn’t sure where the device was mapped inside the /dev. Digging around, I found these commands:
    • # lsusb (to list all USB devices)
  • I saw that my Seagate drive was detected properly with an entry in the list. Further more, running dmesg, I confirmed that the Linux LiveCD recognized my drive:
    • # dmesg | grep -i “SCSI” (this command is to grep the boot-up kernel messages for the word “SCSI” to make sure the kernel detected the device when it was booting)
  • Cool, but now I thought to myself, “how am I supposed to know which device in the /dev folder is my USB?” Actually I made an educated guess here and got lucky. The USB drive was mapped to the /dev/sdb1. I guess with some greppings through the lsub/ other cryptic linux commands/ blind guesses/ beginner’s luck, you’ll find which entry in the /dev folder is your USB drive. Nonetheless, try /dev/sdb1 first, you never know.
  • With my newly gained knowledge (and power), I was ready to mount my drive and start a mini cloning factory:
    • # mkdir /seagate (to create a new mount folder placeholder)
    • # mount -t ntfs /dev/sdb1 /seagate (to mount the NTFS-formatted USB drive to the /seagate folder)
  • I was able to mount the USB drive to the /seagate folder using the above command. However, it was read-only since the LiveCD OS did not know the linux permission of the drive. I found out about this when the imaging utility partimage failed to write the image file to the drive. The correct mount command to enable Linux permission is
    • # mount -t ntfs-3g /dev/sdb1 /seagate (notice the ntfs-3g param)

    Afterwards I was able to write a test file to my USB drive ( #echo “test” > /seagate/test.txt ) and seeing all the Linux permissions on the files ( # ll /seagate )

  • I then started partimage. I selected my partition to be imaged, put in the filename in the “Image path” box (/seagate/d830). I didn’t bother with the gzip since I really just image this one time. For my laptop, imaging 10GB took 7 minutes. The files on the USB drive was spillted into files like “d830.000“, “d830.001“, etc.
  • I then unmount the USB drive with
    • # umount -f /seagate

    I remember the LiveCD complained about some other processes were also accessing the device. To find out which process was using the resource, I did a

    • lsof | grep /seagate (list all processes that are opening the /seagate folder)

    Ah, I had a XTerm which I had CD’ed into the /seagate folder. Silly me! I cd to another folder and afterwards, umount was able to finish its job.

Restoring the image

  • Since the replacement one is an exact duplicate, I didn’t have to pay much attention to the partition image. I popped the SystemRescueCD in, switched the USB drive to connect to the replacement laptop, and booted it up with the CD.
  • I went through almost the exact same steps as above: mount the drive using the -ntfs-3g param, then start partimage. Only this time I chose “Restore” instead of creating image and the file name was “/seagate/d830.000“. Partimage automatically picked up the rest.
  • The entire restoring process took another 7 minutes.

I restarted the laptop and crossed my fingers. To my delight, my Windows XP Pro was up and running, even my fingerprints profile was loaded correctly. I swiped my finger, smiled to myself, and thought that it wasn’t too bad, at least I didn’t have to use Norton Ghost — everything was open-source. Just have to love it!

Final Words

I hope you enjoy this post and find it useful. Now I have to finish up posting this blog, pack the original laptop to send it back to Dell, and get busy finding a piece of paper to fix the battery issue for the replacement laptop. Then I can resume doing Rails and Wars of Earth…

Links & References

view comments
 

VS2005 LogoSince these days I practically live inside Visual Studio (and e editor at night for RoR), here is a small list of shortcuts for Visual Studio. These shortcuts will vary depend on your coding environment, but so far these I have tested to work for VB# environment in VS2005.  Enjoy!

“CTRL + K” chorded shortcuts
(Just hold CTRL down and type “K” then “N” for example)

  • CTRL + K, C: comment out the selected lines
  • CTRL + K, U: un-comment out the selected lines.
  • CTRL + K, K: new bookmark
  • CTRL + K, N: jump to next bookmark
  • CTRL + K, P: jump to previous bookmark
  • CTRL + K, F: format the selected lines
  • CTRL + K, I: show summary for the current token (e.g. variable type, Class summary, etc.)

Code Manipulations

  • CTRL + Shift + Space: show signature/ parameters info for the current function. Use Up/Down arrow key to go through list as usual
  • CTRL + Space: show Intellisent Popup.
  • CTRL + L: cut the current line
  • CTRL + Shift + L: delete the current line
  • CTRL + U: convert to lower case
  • CTRL + Shift + U: convert to uppercase
  • I can’t resist to include the highly addictive chorded shortcut CTRL + K + C/U for quickly commenting/ uncommenting code block
  • CTRL + Shift + F: Find for multiple files
  • CTRL + Shift + H: Find & Replace for multiple files
  • CTRL + F: find in current document.
    • F3: find next
    • Shift + F3: find previous
  • CTRL + K, I: show summary for the current token (e.g. variable type, Class summary, etc.)

Code Maneuvering

  • F12: go to definition
  • Shift + F12: go to declaration
  • CTRL + - (hyphen): jump to previous position
  • CTRL + Shift + - (hyphen): jump to next
  • CTRL + G:  go to line #

Regions/ code blocks

  • CTRL + M, O: Collapse all region blocks
  • CTRL + M, M: toggle current block (such as collapsing/ expanding a method block)
  • CTRL + M, P: toggle comment block (?)
  • CTRL + M, L: Expand/ Collapse All

Build-Debug

  • CTRL + Shift + B : build solution
  • CTRL + F5: Run without Debugging
  • Shift + F5: Break Debugging (VS2005 default key combination for this is changed, but you can reassign back to the “conventional” VS2003 way. Or use Shift + Break - the new combination)
  • F9: set breakpoint
  • CTRL + Shift + F9: clear all breakpoints
  • CTRL + ALT + V, L: Open Locals Window (Debug)
  • CTRL + ALT + V, A: Open Autos Window (Debug)
  • CTRL + ALT + C: Open Call stack Window (Debug)
  • Ctrol + Alt + W, [1,2,3,4]: Open Watch windows (Debug)

Miscellaneous

  • CTRL + Tab: switch between opening files. Hold
  • CTRL + PAGE UP/ DOWN: tab between available “view” of the currently opened document (e.g. Design view, Source View, etc.)
  • CTRL + W: select the word under the current caret position. (Watch out for this since in both IE and FF, CTRL W will close the current tab.)
  • ALT + Mouse Drag: Retangular block selection (e editor also has this feature and make it even better)
  • CTRL + I, then type the search word, then F3: incremental search (a.k.a. search-in-place)

Important Windows

  • CTRL + ALT + L: Solution Explorer
  • CTRL + ALT + K: Task List
  • CTRL + ALT + O: Output
  • CTRL + Shift + C: Class View
  • CTRL + ALT + V, L: Locals (Debug)
  • CTRL + ALT + V, A: Autos (Debug)
  • CTRL + ALT + C: Call stack (Debug)
  • CTRL + ALT + W, [1,2,3,4]: Watch windows (Debug)
  • CTRL + ALT + V, [1,2]: Find Results windows

Productivity Enhancements

  • Any comments with TODO keyword can be listed in the Task List window. (You may have to switch to “Comments” instead of User Tasks) [now I’m pretty excited since both RoR’s “rake notes” and VS2005’s Task List both use the same TODO format — one less thing to remember!]

Links
This list is compiled by myself, but here are some other useful links for Visual Studio shortcuts:

view comments