The future of nugget functionality

I’ve spent some of today updating my “jQuery plugin”, doWhen, with the added help of a splendid chap and coworker, name of Erin Swenson-Healy. He adapted it to be more AMD friendly, and I expounded upon that. Basically, now, using requirejs, we can simply say in a given file:

define(["doWhen"],
function(doWhen){
  doWhen(....);
});

Which means for our purposes, it’s not really a jQuery plugin. And, realistically, it’s not. It’s just a tiny nugget of functionality we want to pull in. All it uses from jQuery is a flat extend, and that is easily replaceable (as it already is in the “plain” version).

However, not everybody will consume doWhen through AMD or a similar method. And not everybody who doesn’t necessarily uses jQuery. But I need *somewhere* to attach it to, if AMD or equivalent is not defined.

So, I’m thinking of ditching the jQuery requirement entirely. The “plain” version would be the only one. If AMD or something like it is present, it would define according to that pattern. If jQuery, underscore, or another common library is present, it would attach to one or more of those for more traditional use, defaulting perhaps to the global object if none are present?

doWhen

It occurs to me that I have neglected to post about the most bloody useful utility I’ve ever written: doWhen

While the main version is a jQuery plugin, I find myself using the non-jQuery version more often, so that’s the one I’ll describe here.

What doWhen does is allow you to create a single “virtual event” in the form of a test function which, when it returns true, runs a callback function.

Let’s say we were loading a library and wanted a quick way to do something when the library is ready:

<script type="text/javascript">
var global = (function(){return this;}());
Event.doWhen(function(){
  return !!global.jQuery;
}, function(){
  alert('jQuery loaded!');
});
</script>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.min.js"></script>

The !! ensures the result is a boolean. Every 100 milliseconds (configurable), it will run the first function. The first time that function returns true, it runs the second function.

I use this extremely frequently, even in wee code snippets, thanks to the tiny footprint (about 1/3kB minified).

See the github page for options.

Open question: is Event the place to put this? Keep in mind this isn’t extending the object’s prototype, so shouldn’t cause conflicts in other code.

I am considering whether there’s a need for an ajax capable one which periodically checks a remote state.

JWPlayer and Firefox hunting

Greetings m’chums! Welcome to this week’s big adventure: trapping and shooting an old bug in a very popular tool.

In the course of my everyday tinkering, I encountered a curious flaw in JWPlayer under Firefox which I think has plagued fellow adventurers of this fine Flash movie player for years, but which none seem to have sussed the essential nature of. Until today.

It all started when I found the player was firing no events. Initial investigation showed that I was never subscribing the events, because I was waiting for the event attaching method jwAddEventListener to arrive on the scene:

var player = $('#myplayer');
$.doWhen(function(){
  return !!player.jwAddEventListener;
}, function(){
  //attach events
});

(doWhen is a nifty little utility I wrote that runs one function once after another function returns true)

A full investigation of the matter revealed that, in Firefox, the entire Javascript API for the embed was never being created! This was quite curious, as I’ve had many players fully functional in Firefox before.

I set about identifying what was different, and at last deduced that in all the previous cases, I had been instantiating the player after an ajax call (for content). In this case, however, the player was being created immediately after jQuery(document).ready.

Pausing briefly to brew up another cup of brown joy strong enough that the spoon stood rigid, I continued the experiment by delaying the player instantiation by two seconds with setTimeout. Lo and behold, the missing API was rumbled!

This was far from an ideal solution, of course. I wondered at what critical juncture Firefox would be in a position to correctly instantiate JWPlayer. Time to dust off an old friend: window.onload. A quick test showed that yes, indeed, once the load event had fired off, the player’s entire API reappeared like Manchurians at a near-dead pub advertising half-off pints of Brown!

Naturally, I didn’t want to slow other browsers down unnecessarily, so I knew that the final solution would have to narrow its sights on Mozilla, and only if the load had not yet fired. The way to determine the latter is document.readyState: “interactive” means the page is still in its initial rendering phase, but the DOM is available; “complete” is the word we’re looking for, the readyState when load has fired.

if ($.browser.mozilla
      && document.readyState !== 'complete') {
  $(window).bind('load', function(){
    //write your embed code here
  });
} else {
  //write your embed code here
}

There you have it! Clearly, this should not be necessary; JWPlayer should do all of this internally. For now, it’s a workaround that seems 100% successful.

And with that, another successful week tromping through the deepest woods of my trade draws to a close. I bid your weekend be filled with lakes of Earl Grey and barrels of gorgeous Somerset gold. Tata!

More on Randomness of Arrays

A few months ago, I posted about how the classic method most JS programmers would use to randomise an array completely fails. I proposed a quick solution to it, but that solution had flaws of its own.

So, for those of you who need to shuffle decks of cards, scramble virtual eggs or just want to toss a little confusion into your applications, here’s a fully working array randomiser:

Array.randomiseArray = function(arr){
  var i, v;
  for (i=0; i<arr.length; i++) {
    v = arr[i];
    arr[i] = {
      v: v,
      sort: Math.random()
    };
  }
  arr.sort(function(a, b){
      return a.sort - b.sort;
  });
  for (i=0; i<arr.length; i++) {
    arr[i] = arr[i].v;
  }
  return arr;
};

SMIRF 2.0

Late last year, I told you about the SMIRF JS pattern I’ve been working on. Since then, I’ve had quite a lot of opportunity to use it in the field and refine it.

The biggest weakness with the old SMIRF pattern was the need to pass the instance variables around all the time. It meant there was a tiny memory leak in the api, since wrapper functions needed to add the iVars argument to all calls.

What I’ve changed is that iVars is now accessed via a method getIVars┬áin the “constructor”. There’s a localised randomly generated private key which must be passed in to get the instance variables. That way, nothing outside could grab them and clobber them (unless you write a method to deliver them, obviously!

So, here’s the updated pattern:

var employeeFactory = (function(){
  var PRIVATE_KEY = String(Math.random()), giveRaise, fire;
  
  giveRaise = function(percent){
    var iVars = this.getIVars(PRIVATE_KEY);
    percent = percent || 0;
    console.log(iVars.salary);
    iVars.salary = iVars.salary * (1 + (percent/100));
    return iVars.salary;
  };
  fire = function(){
    var iVars = this.getIVars(PRIVATE_KEY);
    //long, drawn out legal process that takes 5000 lines
    iVars.currentlyEmployed = false;
  };
  
  return function(name, salary){
    //This is essentially a constructor function
    var iVars = {
      //Instance variables. All state info should be stored here
      name: name,
      salary: salary,
      currentlyEmployed: true
    };
    return {
      getIVars: function(key){
        if (key === PRIVATE_KEY) {
          return iVars;
        }
      },
      giveRaise: giveRaise,
      fire: fire
    };
  };
}());
var employee1 = employeeFactory('Bob', 30000);
var employee2 = employeeFactory('Mary', 21000);

An Array of Random Thoughts

Today, I was asked to supply a way (in Javascript) to create an array of all integers 0-9, but randomised, with no duplicates. Immediately, I gave this solution:

var arr = [0,1,2,3,4,5,6,7,8,9].sort(function(){
  return 0.5 - Math.random();
});

That should do it, right? Well, one of the tests that was run on the resulting “random” array was to see whether or not the first five members were consistently even or odd:

var generateRands = function(){
  return [0,1,2,3,4,5,6,7,8,9].sort(function(){
    return 0.5 - Math.random();
  });
};
var isMoreEven = function(arr){
  var i, even = 0, odd = 0;
  for (i=0; i<5; i++) {
    if (arr[i] % 2) {
      odd++;
    } else {
      even++;
    }
  }
  return even > odd;
};
var runTests = function(iterations){
  var i, even = 0, odd = 0, arr;
  for (i=0; i<iterations; i++) {
    arr = generateRands();
    if (isMoreEven(arr)) {
      even++;
    } else {
      odd++;
    }
  }
  console.log('even won', even, 'or', (even/iterations * 100) + '%',
    '; odd won', odd, 'or', (odd/iterations * 100) + '%');
};
runTests(10000);

The expected result would be that even and odd would hover around 50%, with some variance either way. Here’s what it *actually* outputs:

even won 6762 or 67.62% ; odd won 3238 or 32.379999999999995%

WTF? It hovered consistently around this ratio with every test! I thought at first that it was perhaps a pattern in the pseudo random number generator, but no matter what I did, it hovered strongly in favour of even.

Keep in mind this is the method most commonly recommended on tutorial sites around the net for randomising an array’s order!

I added a further test to this, to see how frequently each number ends up in the first five. Here’s the test:

var runTests = function(iterations){
  var i, j, arr, nums = [], order = [];
  for (i=0; i<10; i++) {
    nums.push({
      num: i,
      count: 0
    });
  }
  for (i=0; i<iterations; i++) {
    arr = generateRands();
    for (j=0; j<5; j++) {
      nums[arr[j]].count++;
    }
  }
  nums.sort(function(a, b){
    return a.count - b.count;
  }, true)
  for (i=0; i<10; i++) {
    order.push(nums[i].num + ' (' + nums[i].count + ')');
  }
  console.log(order);
};
runTests(10000);

The output was consistently something like this:

["9 (309)", "8 (598)", "7 (1180)", "6 (2256)", "5 (3963)",
  "4 (6170)", "3 (7926)", "2 (8817)", "1 (9386)", "0 (9395)"]

The number in parentheses represents the number of times in 10000 that the number to the left appeared in the top five. This “random” sort didn’t seem to take array members very far from home. One and zero are the only two that I could get to swap how frequently they appeared in the first five, for some reason.

What I finally realised was that the flaw was in my use of sort. Sort swaps adjacent items until it reaches the conclusion that the array is in the proper order. Each item is “less than” or “greater than” the other, and this is meant to be a consistent value. If you randomise the compare function’s output, then it will swap items, then swap them back, and finally give up on your inconsistency.

Even was coming up more often than odd because there are a greater number of even numbers from 0-4.

And now, what you probably visited this page for. A *working* array randomiser:

UPDATE: I have a much better method now in this post!

var randomSort = function(arr){
  var i, l, sortOrder = {};
  for (i=0, l=arr.length; i<l; i++) {
    sortOrder[arr[i]] = Math.random();
  }
  return arr.sort(function(a, b){
    return sortOrder[a] - sortOrder[b];
  });
};
var generateRands = function(){
  return randomSort([0,1,2,3,4,5,6,7,8,9]);
};
for (var i=0; i<5; i++) {
  runTests(10000);
}

This worked! Here’s the output:

["4 (4933)", "0 (4953)", "7 (4983)", "6 (4990)", "9 (5002)",
  "5 (5010)", "1 (5017)", "3 (5029)", "2 (5038)", "8 (5045)"]
["9 (4915)", "4 (4940)", "2 (4941)", "8 (4957)", "5 (4974)",
  "7 (5011)", "3 (5044)", "1 (5046)", "0 (5077)", "6 (5095)"]
["2 (4947)", "4 (4963)", "5 (4977)", "0 (4987)", "3 (4988)",
  "9 (5002)", "6 (5013)", "1 (5022)", "7 (5034)", "8 (5067)"]
["8 (4871)", "4 (4938)", "9 (4962)", "1 (4977)", "0 (4989)",
  "2 (4993)", "3 (5012)", "6 (5051)", "7 (5057)", "5 (5150)"]
["7 (4944)", "3 (4953)", "8 (4968)", "5 (4976)", "0 (4991)",
  "4 (5017)", "1 (5024)", "6 (5028)", "2 (5030)", "9 (5069)"]

The even/odd test above works with this new method, too.

I just wonder how many faulty array shuffling implementations are out there that don’t work!

Note: This randomSort is not perfect! Identical array values will end up adjacent to one another.

The Static Module Instance wRapper Factory (SMIRF) pattern

Earlier in the year, I wrote about memory waste issues in Caveats of the JS Module Pattern. I’d like to offer a new pattern as a solution to those issues.

First, a reminder of why we like the module pattern: it provides an elegant way to have private methods and variables. For most singleton objects, there is no better option. I’ll use Christian Heilmann’s Revealing Module pattern for my examples:

var currencyExchange = function(){
  var currencies = {
    usd: 1,//always 1, base currency
    gbp: 0.631552356,
    aud: 0.99980004,
    cad: 1.0072999
  };
  var convert = function(fromCurrency, toCurrency, amount){
    var amountInUsd = (fromCurrency === 'usd') ?
      amount : amount / currencies[fromCurrency];
    return (toCurrency === 'usd') ?
      amountInUsd : amountInUsd * currencies[toCurrency];
  };
  var changeRate = function(currency, rate){
    currencies[currency] = rate;
  };
  return {
    convert: convert,
    changeRate: changeRate
  };
}();

The memory waste problem occurs when you use this pattern to create object instances:

var employeeFactory = function(name, salary){
  var giveRaise = function(percent){
    salary = salary * (1 + (percent/100));
    return salary;
  };
  var fire = function(){
    //long, drawn out legal process that takes 5000 lines
  };
  return {
    giveRaise: giveRaise,
    fire: fire
  };
};
var employee1 = employeeFactory('Bob', 30000);
var employee2 = employeeFactory('Mary', 21000);

We now have created two identical but separate versions of the giveRaise and fire functions, wasting CPU in generating the duplicates, and memory in storing them.


SMIRF it down to size

Looking at the singleton example, the elegance of it is that the functions are created once as the script is first run. The reason we can’t easily do that with instantiation is that the functions need to be declared in the scope of the state variables (name and salary) that they’re operating on.

The SMIRF pattern provides a way to have the outer, static module which provides methods shared across all instance objects, avoiding most of the CPU and memory waste.

We still need to create tiny, one line “wrapper” methods for each method on an instance, but the footprint of these is minimal in comparison to that of reproducing large methods for each instance.

var employeeFactory = function(){
  /* These are STATIC functions to hold the majority of code.
   * They should be run in the context of the instance via "call",
   * and the first arg should always be iVars.
   * The "this" keyword and iVars are the only ties these methods
   * have to the object!
   */
  var giveRaise = function(iVars, percent){
    iVars.salary = iVars.salary * (1 + (percent/100));
    return iVars.salary;
  };
  var fire = function(iVars){
    //long, drawn out legal process that takes 5000 lines
  };
  return function(name, salary){
    //This is essentially a constructor function
    var iVars = {
      //Instance variables. All state info should be stored here
      name: name,
      salary: salary
    };
    var instance = {
      //This will be our actual instance object.
      //Fns here are thin wrappers for memory efficiency
      giveRaise: function(percent){
        return giveRaise.call(instance, iVars, percent);
      },
      fire: function(){
        return fire.call(instance, iVars);
      }
    };
    return instance;
  };
}();
var employee1 = employeeFactory('Bob', 30000);
var employee2 = employeeFactory('Mary', 21000);

Note that the methods on the instance object will never vary much from what you see above. They simply run the static methods in the context of the instance, passing the instance variables, and pass back the returned value.

All private variables should be stored in iVars, so that the static method signature is always the same. Publicly accessible variables, of course, would simply be on the instance object itself, accessible via the “this” keyword in the shared static methods.