28 April, 2009

Essential JavaScript functions.

2009/07/22 Update:
Added Object.keys. Removed String.prototype.*, alert, and waitUntil.
"use strict";
if (typeof Object.create !== "function") {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
if (typeof Object.keys !== "function") {
    Object.keys = function (obj) {
        var name, output = [];
        for (name in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, name)) {
                output.push(name);
            }
        }
        return output;
    };
}

The above are functions I have found indispensable or extremely useful in my programming. They are listed here for convenience.

Object.create

String.prototype
window.alert
window.waitUntil

[LINK] The source code.
[LINK] The unit tests.

window.waitUntil

2009/08/23 Update:
This is only really useful if you need to do asynchronous calls 11 or more times. If you only need to make a few calls, it would be better to just use the (function () {}()); construct.

Here is a new function I have recently created:

"use strict";
var waitUntil = function anon(func, ms) {
    ms = ms || 100;
    if (func() !== true) {
        return setTimeout(function () {
            anon(func, ms);
        }, ms);
    }
};

I don't know about you, but in my code I have to frequently test a condition... but do so asynchronously. You can do this with setTimeout, but it requires a lot of syntax and work to get it right. The above function attempts to ease this a little.

You call it like so:

waitUntil(function () {
    if (test === 5) {
        alert("Done!");
        return true;
    }
});
This is the same as if I had done:
(function anon() {
    if (test === 5) {
        alert("Done");
    } else {
        setTimeout(anon, 100);
    }
}());

Not a huge difference, but still useful when you need to perform such checks on a regular basis. waitUntil accepts two arguments:

  1. This should be a function. waitUntil will continue executing this function until it returns true, which tells waitUntil to stop.
  2. This should be a number. This is how often waitUntil will run the function, in milliseconds. The default is 100.

In addition, waitUntil returns a setTimeout, so you can use clearTimeout to halt the check at any time:

var timer = waitUntil(function () {
    if (test === 5) {
        alert("Done!");
        return true;
    }
}, 300);
clearTimeout(timer);

[LINK] The unit tests.

window.alert

One of the problems with the alert() function is the inability to cancel it when placed within loops. You may find this function useful:
"use strict";
var alert = function anon() {
    if (!anon.stop) {
        anon.stop = !confirm(Array.prototype.join.call(arguments, "\n"));
    }
};
These following lines of code are identical:
// Old:
alert("Hi!");
// New:
alert("Hi!");
// Old:
alert(1 + "\n" + 2 + "\n" + 3);
// New:
alert(1, 2, 3);

However, an even more powerful feature of this new alert() function is that if it is called repeatedly, you can click the "Cancel" button to prevent it from displaying any more alerts!

Credit for the idea goes to this blog. The actual code is all by me, though.

[LINK] The unit tests.

12 April, 2009

Reflecting a vector.

Let us assume:
angle = the angle of the incoming vector.
 wall = the angle of the "wall".

The formula for the reflection of an incoming vector in degrees is:
angle - (2 * (angle + (90 - wall)))
There is also a version in radians, which is very similar:
angle - (2 * (angle + ((PI / 2) - wall)))

06 April, 2009

String.prototype

I have created three (very) simple JavaScript methods for working with strings. Any competent JavaScript programmer could whip these up in 5 minutes; nonetheless, they are useful so I shall share them with you:
"use strict";
if (typeof String.prototype.sort !== "function") {
    String.prototype.sort = function (funct) {
        return this.split("").sort(funct).join("");
    };
}
if (typeof String.prototype.splice !== "function") {
    String.prototype.splice = function (index, length, add) {
        var text = this.split("");
        text.splice(index, length, add);
        return text.join("");
    };
}
if (typeof String.prototype.reverse !== "function") {
    String.prototype.reverse = function () {
        return this.split("").reverse().join("");
    };
}

Let's examine them. All three make use of the string.split() and array.join() methods. These convert a string to an array and an array to a string, respectively.

By passing an empty string "" as the single argument, it creates an array where each index holds a single character of the string. Thus:

var text = "Hi!";

text = text.split("");
// text[0] == "H"
// text[1] == "i"
// text[2] == "!"

text = text.join("");
// text == "Hi!"

Useless? Not so! This allows us to treat a string as an array of characters, and thus pretend that strings are mutable. As a simple example:

var text = "Testing";
text = text.split("");

text[0] = "a";
text[1] = "b";
text[2] = "c";

text = text.join("");
// text == "abcting"

You can also use this to delete characters at specific indices by setting the index to null or "". In this way, you can manipulate strings.

This is very useful, but my methods go a step further by using the built-in Array methods. After adding the above three methods to your program, you can do stuff like this:

var text = "Testing";
text = text.reverse();
// text == "gnitseT"

Or you can use the powerful array.splice() method on strings:

var text = "Testing";
text = text.splice(3, 2).splice(0, 1, "A");
// text == "Aesng"

The first splice removes the characters at index 3 and 4 (remember, the second argument is the length, not the index!). The second splice removes the first index and inserts the string "A", producing the final result. Because all three methods return strings, you can chain them together, as shown above.

There are two differences between string.splice() and array.splice():

  1. string.splice() returns a string, which is the source string with the splice method applied. On the other hand, array.splice() returns an array of the removed values.
  2. string.splice() accepts up to 3 arguments. It ignores any arguments beyond the 3rd. array.splice() accepts an unlimited number of arguments.

    This is not a bug. These two lines are the same:
    string.splice(0, 0, "a", "b", "c");
    string.splice(0, 0, "a" + "b" + "c");
    Because extra arguments are unnecessary, I snipped them out for performance reasons.

Beyond those two differences, string.splice() performs identically to array.splice().

The third method is string.sort(). This performs identically to array.sort(), so please consult your favorite JavaScript manual for information on how to use it.

Note: I did not include the other Array methods because they are either useless (like array.concat()), can be simulated with array.splice() (array.pop(), array.push(), etc.), or already have a String equivalent (array.slice()).

Note: Beyond the two differences listed for string.splice(), all three methods perform identically to their Array counterparts.

[LINK] The unit tests.

References:
[MDC] [w3] array.sort()
[MDC] [w3] array.splice()
[MDC] [w3] array.reverse()