Thing = function() {
    this.init = function(x, y, w, h, str, intensity) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.str = str;
        this.intensity = intensity;
        return this;
    };

    this.draw = function(ctx) {
      var r = 0;
      var g = 0;
      var b = 0;
      var a = 1.0 * this.intensity;
      ctx.fillStyle = "rgba(" + r + ", " + g + "," + b + "," + a + ")";
      ctx.fillText(this.str, this.x, this.y);
    };
};

Queue = function() {
    this.init = function() {
        this.queue = [];
        return this;
    };
    this.enqueue = function(obj) {
        this.queue.push(obj);
    };
    this.dequeue = function() {
        return this.queue.shift();
    };
    this.draw = function(ctx) {
        var style;
        for (var i = 0; i < this.queue.length; i++) {
            this.queue[i].draw(ctx);
        }
    };
    this.fade = function(amount) {
        for (var i = 0; i < this.queue.length; i++) {
            this.queue[i].intensity -= amount;
            this.queue[i].y += 1;
        }
        while (this.queue.length > 0 && this.queue[0].intensity <= 0) {
            this.queue.shift();
        }
    };
};

Fingerspelling = function() {
    var intervalId;

    var canvas;
    var ctx;
    var queues = [new Queue().init(), new Queue().init()];
    var touches = [undefined, undefined];

    this.draw = function() {
        for (var touchNum = 0; touchNum <= 1; touchNum++) {
            var touch = touches[touchNum];
            if (touch === undefined) continue;

            for (var i = 0; i <= 1; i++) {
                var range = 32;
                var offX = Math.random() * (range*2) - range;
                var offY = Math.random() * (range*2) - range;
                var thing = new Thing();
                var val;
                if (touchNum == 0) {
                    val = Math.floor(Math.random() * 26 + 65);
                } else {
                    val = Math.floor(Math.random() * 26 + 97);
                }
                var letter = String.fromCharCode(val);
                thing.init(touch.canvasX + offX,
                           touch.canvasY + offY, 0, 0, letter, 1.0);
                queues[touchNum].enqueue(thing);
            }
        }
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        for (var touchNum = 0; touchNum <= 1; touchNum++) {
            queues[touchNum].draw(ctx);
            queues[touchNum].fade(0.05);
        }
        var e = document.getElementById('status');
        if (e) {
            e.innerHTML = 'Letters: ' + queue.queue.length;
        }
    };

    this.init = function(c, imgUrl) {
      canvas = c;
      c.left = 0;

      var resizeCanvas = function(e) {
          canvas.width =
              document.documentElement.clientWidth - canvas.offsetLeft * 2;
          canvas.height =
              document.documentElement.clientHeight - canvas.offsetTop - 5;
          ctx = canvas.getContext("2d");
          ctx.textBaseline = "top";
          ctx.font = "24px Serif";
      };
      window.addEventListener("resize", resizeCanvas);
      resizeCanvas();

      var mouseTN = 0;
      canvas.addEventListener('mousedown', function(e) {
          touches[mouseTN] = {};
          touches[mouseTN].canvasX = e.pageX - canvas.offsetLeft;
          touches[mouseTN].canvasY = e.pageY - canvas.offsetTop;
          e.preventDefault();
      });
      canvas.addEventListener('mouseup', function(e) {
          touches[mouseTN] = undefined;
          e.preventDefault();
      });
      canvas.addEventListener('mousemove', function(e) {
          if (touches[mouseTN] !== undefined) {
              touches[mouseTN].canvasX = e.pageX - canvas.offsetLeft;
              touches[mouseTN].canvasY = e.pageY - canvas.offsetTop;
          }
          e.preventDefault();
      });

      canvas.addEventListener('touchstart', function(e) {
          for (var touchNum = 0; touchNum <= 1; touchNum++) {
              var touch = e.touches[touchNum];
              if (touch === undefined) continue;
              touches[touchNum] = {};
              touches[touchNum].canvasX = touch.pageX - canvas.offsetLeft;
              touches[touchNum].canvasY = touch.pageY - canvas.offsetTop;
          }
          e.preventDefault();
      });
      canvas.addEventListener('touchend', function(e) {
          // not great, but ehh.
          touches = [undefined, undefined];
          e.preventDefault();
      });
      canvas.addEventListener('touchmove', function(e) {
          for (var touchNum = 0; touchNum <= 1; touchNum++) {
              var touch = e.touches[touchNum];
              if (touch === undefined) continue;
              touches[touchNum].canvasX = touch.pageX - canvas.offsetLeft;
              touches[touchNum].canvasY = touch.pageY - canvas.offsetTop;
          }
          e.preventDefault();
      });

      var self = this;
      intervalId = setInterval(self.draw, 20);
    };
};

@@ -65,16 +65,25 @@
 ntensity
+, r, g, b
 ) %7B%0A    
@@ -230,147 +230,135 @@
     
-return this;%0A    %7D;%0A%0A
+this.r = r %7C%7C 0;%0A   
     
+ 
 this.
-draw = function(ctx) %7B%0A      var r = 0;%0A      var g = 0;%0A      var b = 0;%0A      var a = 1.0 * this.intensity;
+g = g %7C%7C 0;%0A        this.b = b %7C%7C 0;%0A        return this;%0A    %7D;%0A%0A    this.draw = function(ctx) %7B
 %0A   
@@ -386,16 +386,21 @@
 gba(%22 + 
+this.
 r + %22, %22
@@ -402,16 +402,21 @@
  %22, %22 + 
+this.
 g + %22,%22 
@@ -416,16 +416,22 @@
  + %22,%22 +
+ this.
  b + %22,%22
@@ -433,17 +433,36 @@
 + %22,%22 + 
-a
+1.0 * this.intensity
  + %22)%22;%0A
@@ -1280,16 +1280,33 @@
 ervalId;
+%0A    var options;
 %0A%0A    va
@@ -2251,16 +2251,85 @@
 ter, 1.0
+,%0A                           options.red, options.green, options.blue
 );%0A     
@@ -2784,14 +2784,12 @@
 (c, 
-imgUrl
+opts
 ) %7B%0A
@@ -2823,16 +2823,164 @@
 eft = 0;
+%0A      options = opts %7C%7C %7B%7D;%0A      options.red = options.red %7C%7C 0;%0A      options.green = options.green %7C%7C 0;%0A      options.blue = options.blue %7C%7C 0;
 %0A%0A      

Make text colour in Fingerspelling configurable.