JasonWyatt

This blog is full of stuff, and things.

Find my resume.

permalink

An Update to jQSlickWrap

Earlier today, @AlmogBaku submitted the first ever pull request to the github project for jQSlickWrap. He added the ability to have the image rendered as the background-image of the parent div by its src parameter, as opposed to using a data-URI. I think this approach may be better than the data-URI mechanism I was using before, so maybe it’ll become the default in the future.

Additionally, while testing the pull request I realized that there was a bug with how the height of parent divs was being set (to make sure the entire image showed.) If you were to resize the window after jQSlickWrap did its business a couple of things could happen: the image could get chopped-off, or the text could overflow the containing div. This behavior has been corrected.

Thanks to these changes, I’ve upped the version number of jQSlickWrap to 0.2. You can read more about the project and download it from the jQSlickWrap home page. These are the first substantial changes to the code since it was released in 2009!

It really is something special to receive a pull request from a total stranger on a project you created.

permalink

Algorithms in JavaScript: Binary Search

I’m going to start a new blog series: Algorithms in JavaScript. This first article will discuss the implementation of “Binary Search”.

The Problem

You’ve got a huge array of sorted values and you need to find the location in that array of a particular value (or whether that value exists within the list at all.)

Brute Force (And Why It Sucks)

The simplest approach to finding the location of your target value within a sorted list of values is to iterate through the list one-by-one until you:

  1. find the target value (returning the location when found), or
  2. find a value greater-than the target value (returning null because this means the target can’t possibly exist in the array.)

Why does it suck? Consider the case when you’re given an array containing a million elements and your target is nowhere to be found: you’ll have to look at every element in the array! In computer science parlance, this worst-case situation of having to look at every element in the array means that the algorithm is O(n) (read “Big-Oh of n”) and its run-time will increase linearly with the size of the search array.

“Binary” Searching

Instead of looking at every element in the array from lowest to highest: let’s look at the middle of the array first and if it’s greater than our target we’ll search in the first half of the array, if it’s lesser than the target we can search in the second half of the array, and if it’s equal to the target - our answer is the middle index. You keep repeating this pattern of cutting the array in half until you either find the target or run out of array (and hence: didn’t find the target).

If you’re still confused, think of it like the days before the internet when you would have to “let your fingers do the walking” to search a phone book for your friend’s number. You’d crack the book open somewhere in the middle and look at one of the names on the page. If your friend’s name comes before that name you’ll look in the chunk of pages to the left of the current page, if it comes after that name you will look in the other chunk of pages, and if it’s pretty close to the name you found at first - you’re in luck and just have to scan the current page for your friend (using binary search again!)

Because we’re repeatedly cutting our search space in half with each iteration, and we’re only evaluating the endpoints and median of the space each time we can say that Binary Search performs in O(log n) time (this series won’t deal with proving this type of thing, but you can find plenty of proofs online with a quick visit to google.) What this means is that even when searching within a million-item array, we’ll only end up iterating about twenty times at the worst case. That’s 50,000 times faster than the worst case of the brute-force situation!

Pseudocode

function search(array, target, start, end):
    if start > end:
        return NOT_FOUND
    if array[start] is target:
        return start
    if array[end] is target:
        return end
    middle = ( start + end ) / 2
    if array[middle] > target:
        return search(array, target, start+1, middle)
    if array[middle] < target:
        return search(array, target, middle, end-1)
    return middle

You would call the above function with start = 0 and end = array.length-1.

Binary Search in JavaScript

The following code is also available with a demo application on jsbin.

function binarySearch( sortedValues, target ){
  // summary:
  //    Performs a binary search on an array of sorted 
  //    values for a specified target. 
  // sortedValues: Array
  //    Array of values to search within.
  // target: String|Number
  //    Item to search for, within the sortedValues array.
  // returns:
  //    Number or null. The location of the target within
  //    the sortedValues array, if found. Otherwise returns 
  //    null.
  
  // define the recursive function.
  function search( low, high ) {
    // If the low index is greater than the high index, 
    //  return null for not-found. 
    if ( low > high ) {
      return null;
    }
    
    // If the value at the low index is our target, return 
    //  the low index.
    if ( sortedValues[low] === target ){
      return low;
    }
    
    // If the value at the high index is our target, return
    //  the high index.
    if ( sortedValues[high] === target ){
      return high;
    }
    
    // Find the middle index and median element.
    var middle = Math.floor( ( low + high ) / 2 );
    var middleElement = sortedValues[middle];
    
    // Recursive calls, depending on whether or not the 
    //  middleElement is less-than or greater-than the 
    //  target.
    // Note: We can use high-1 and low+1 because we've 
    //  already checked for equality at the high and low 
    //  indexes above.
    if ( middleElement > target ) {
      return search(low+1, middle);
    } else if ( middleElement < target ) {
      return search(middle, high-1);
    }
    
    // If middleElement === target, we can return that value.
    return middle;
  }
  
  // Start our search between the first and last elements of 
  //  the array.
  return search(0, sortedValues.length-1);
}

What other algorithms would you like to see discussed and implemented with JavaScript?

permalink

Google Maps API in an AMD Module (RequireJS / Dojo)

At my day job I do a lot of work with the Google Maps JavaScript API. We’ve recently been getting more into using RequireJS for our new projects, and one of the things I originally struggled with was that I’d need to include an additional <script> tag in the markup just for Google Maps.

Until I discovered how to wrap the Google Maps API in an AMD Module:

This module can be used by both RequireJS and Dojo users.

permalink

How to correctly debounce a JavaScript function.

This function correctly debounces a function that is anticipated to be called many times with identical input in a short amount of time:

permalink

Singleton Pattern with RequireJS

Here’s a quick Gist on how to create a singleton with RequireJS.

permalink

How to kick off a TestSwarm job from jQuery…

Towards the end of last week I set up an instance of John Resig’s TestSwarm server here at TransLoc. In case you’re not familiar with it, here’s an excerpt of the description from the TestSwarm wiki at GitHub:

TestSwarm provides distributed continuous integration testing for JavaScript. It was initially created by John Resig as a tool to support the jQuery project and has since moved to become an official Mozilla Labs project.

I’ve got to admit, I’m blown away by the elegance with which TestSwarm solves such a complicated problem. Basically, you throw TestSwarm’s PHP contents onto a LAMP server, create some Cron Jobs or Post-Commit Hooks to watch your version control system, point browsers at your server, then sit back and watch the results come in.

Unfortunately, in the current version of TestSwarm there is no simple way to kick off test jobs without a cron job/hook. Apparently, there used to be a web-based form that would work, but it seems to be missing.

Below, you’ll find a really quick $.ajax() invocation that will initiate a test job on a TestSwarm server. Just make sure that the “urls” parameter contains urls with valid QUnit/DOH/etc. test modules that can be accessed by the swarm’s browsers (i.e. not filesystem urls on your development machine).

$.ajax({
    data: {
        state: "addjob",
        output: "dump",
        user: "[Your User Name]",
        auth: "[Your Authentication Key]",
        max: 5,
        job_name: '[Whatever name you want]',
        browsers: 'all',
        'suites': [
            "Suite 1",
            "Suite 2",
            "Suite 3",
            "Suite 4"
        ],
        'urls': [
            "http://url/to/test/suite/1.html",
            "http://url/to/test/suite/2.html",
            "http://url/to/test/suite/3.html",
            "http://url/to/test/suite/4.html"
        ]
    },
    url: 'http://[your testswarm location]',
    traditional: true,
    success: function(data){
        console.log(data);
    }
});

The nice thing about this little script is that it can be run from within Firebug or the Webkit developer tools in a browser that’s already pointed at your TestSwarm server (because it includes jQuery for you).

permalink

We put together a video showing time lapse of the development process behind a new feature for TransLoc.

permalink

Anonymous Classes with JavaScript and Self-Calling Functions

I was messing around with Firebug today, trying to test out a concept for event handling and I didn’t want to have to go through all the pomp and circumstance of creating a legitimate class in the firebug console so I dreamed up a way to make an anonymous class. Here’s what I came up with: (I left out the event handling stuff)

var a = new (function(name){
    this.sayHello = function(){
        console.log("Hello, ", name, "!");
    };
})("Jason");

a.sayHello();

What’s going on here? Remember that classes in JavaScript are just functions that can be called with the new keyword to instantiate a new object of the class defined by that function. (the function acts as the class’s constructor) So, we’re setting a variable, a, to a new instance of a class whose constructor is an anonymous function wrapped in parentheses to encapsulate it.

We can take this concept even further by working with our anonymous class’s prototype after we instantiate it. However, I cant really think of a practical reason to do this other than to make the code prettier, if you know - leave a comment.

var a = new (function(name){
    this.name = name;

    this.sayHello = function(){
        console.log("Hello, ", this.name, "!");
    };
})("Jason");

a.constructor.prototype.sayGoodbye = function(){
    console.log("Goodbye, ", this.name,".");
};

a.sayHello();
a.sayGoodbye();

Why do I care?

Anonymous classes can be useful for things like mock objects in the case of unit tests. Imagine that you have a unit test which checks that a static method called serialize() correctly serializes an instance of its class, MyClass to a JSON string. We don’t really want to create a new instance of the real class if we only need to check that certain attributes are correctly serialized. Check it out:

/* 
 Lots of code to describe MyClass
 */
MyClass.serialize = function(instance){
    return JSON.stringify({
        name: instance.getName(),
        longList: instance.getList()
    });
};

/*
 In another file, for our unit test...
 */
function testSerialize(){
    var data = {
        name: "Awesome object.",
        longList: [1,2,3,4]
    };

    var actualResult = MyClass.serialize(new (function(settings){
        this.getName = function(){
            return settings.name;
        }
        this.getList = function(){
            return settings.longList;
        }
    })(data));

    assertEqual(JSON.stringify(data), actualResult);
}

I realize that this probably isn’t all that novel, but it’s an example of how JavaScript is a great language for allowing programmers to be creative.