## HOWTO: Convert relative URL to absolute URL You may not need to do this; the `href` attribute of `a` elements is converted for you. ## TIP: Change the length of an array foo.length = n; You can also remove all the elements of an array with: foo.length = 0; ## TIP: Array manipulation foo = [1, 2, 3]; foo.push.apply(foo, [4, 5, 6]); // foo is [1, 2, 3, 4, 5, 6] ## TIP: Convert hash to query string var toQueryString = function(hash) { var s = ""; for (var k in hash) if (hash.hasOwnProperty(k)) { if (s !== "") { s += "&"; } s += encodeURIComponent(k) + "=" + encodeURIComponent(hash[k]); } return s; }; Note: if you already have a prototype dependency, use [`Hash.toQueryString`](http://www.prototypejs.org/api/hash/toQueryString) instead. (Most libraries have an equivalent function.) ## HOWTO: Create a proxy object This isn't quite a proper proxy object, but it's about as good as you can get in JavaScript: var Duplicator = Class.create({ initialize: function(listeners) { // Would prefer to trap missing methods dynamically (like PHP's __call), but // this doesn't seem to be possible, so instead create stub methods for all // methods defined by the first listener. var methods = Object.keys(listeners[0]).findAll(function (m) { return m != "initialize" && Object.isFunction(this[m]); }, listeners[0]); methods.each(function (m) { this[m] = function() { var a = arguments; listeners.each(function (obj) { if (Object.isFunction(obj[m])) { obj[m].apply(obj, a); } }); } }, this); } }); var foo = new Foo(); var bar = new Bar(); var dup = new Duplicator([foo, bar]); dup.greet("Michael"); // calls by foo.greet() and bar.greet() ## TIP: JavaScript Scope 1. "In JavaScript, blocks do not introduce a scope. There is only function-scope." http://www.crockford.com/jslint/lint.html (Note that you can nest functions.) 1. "All variables declared in a function, no matter where they are declared, are defined throughout the function." function f() { alert(i); // i exists, and is undefined for (var i = 0; i < 10; i++) { alert(i); } alert(i); // i exists, and is 9 } ("JavaScript: The Definitive Guide," p. 55.) ## HOWTO: Dynamically manipulated select/option drop-downs via JavaScript To delete/remove existing options: el.options.length = 0; To set new options: el.options[i] = new Option('Michael Stillwell', 'mjs'); See * * * ## GOTCHAS: Things IE doesn't do * Doesn't support the click (onclick) event against option elements. See ## HOWTO: Read HTTP status code (trap 404) I don't believe this is possible. XMLHttpRequest will return the status code, but that requires another request. (Also, redirects will be processed by the browser, so if you want the redirect chain you're completely out of luck.) ## HOWTO: Dynamically load JavaScript/write <script> elements var script = document.createElement('script'); script.src = "http://example.com/js/example.js"; script.type = 'text/javascript'; document.getElementsByTagName('head')[0].appendChild(script); (See the [Google Analytics embed](http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&answer=55488) code.) ## HOWTO: Refer to a function from itself e.g. for use in a recursive anonymous function. Use [arguments.callee](http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function:arguments:callee). ## HOWTO: Create an anonymous constructor/class From within a `new function()` block, refer to `arguments.callee.prototype` as above: var instance = new function() { arguments.callee.prototype.greet = function(name) { console.log("Hullo, " + name); }; }; instance.greet("Clem"); // -> "Hullo, Clem" var foo = new instance.constructor(); foo.greet("Mick"); // -> "Hullo, Mick" ## FAQ: What does "new" do? / How do constructors work in JavaScript? When "new" precedes a function call, it does two things: one concerning what "this" refers to within the function, and one relating to the value of the prototype property. When "new Foo()" is called, "new" invokes the function and arranges for the variable "this" within the function to be a reference to a new, empty object. The value of the expression (i.e. the value returned by "new") is "this", unless the function (i.e. constructor) returns a value in which case this value is returned. (However, constructors do not typically return a value.) One implication of this is that anonymous constructors are possible: var user = new function(name) { this.name = name; }; The second thing "new" does is that it sets the prototype property of "this" to be the prototype of the constructor function it was created by. It then sets the "constructor" property of the prototype to the constructor itself. See Chapter 9 of JavaScript: The Definitive Guide ("Classes, Constructors, and Prototypes") for more information. Note that the objects created with `new Foo()` do not have a (visible) `prototype` property--only function objects (i.e. their constructors) do. This also applies to anonymous constructors--meaning that it's typically difficult to modify the prototype property of objects created with an anonymous constructor, because the object itself has no reference to the prototype property. This may not be a problem (if it's anonymous, you typically weren't planning to create a lot of them anyway) but if it is (if you don't want your "methods" to satisfy `hasOwnProperty`, for example), this can be resolved by modifying the prototype directly within the constructor, using `arguments.callee.prototype` to get access to the anonymous function's prototype: var foo = new function(name) { this.name = name; arguments.callee.prototype.bar = function() { return this.name; }; }("Michael"); foo.hasOwnProperty("name"); // true foo.hasOwnProperty("bar"); // false foo.bar(); ## HOWTO: Create automatically changing drop-downs onchange="if (this.options[selectedIndex].value != '') location.href=this.options[selectedIndex].value" ## FAQ: Why doesn't the "onchage" event work with checkboxes in IE? You can poll for changes to a form surprisingly efficiently. A Prototype example: if (Prototype.Browser.IE) { var last_state = $(form).serialize(); var p = new PeriodicalExecuter(function () { var state = $(form).serialize(); if (state != last_state) { last_state = state; // form has changed } }, 0.2); } ## FAQ: What's the Prototype equivalent of ? Event.observe(window, "unload", function() { ... }); ## FAQ: To find the name of an element, should I use `tagName` or `nodeName`? Quirksmode [says `nodeName`](http://www.quirksmode.org/dom/w3c_core.html). ## FAQ: How to do Unicode/UTF-8 compatible sorting? Use `localeCompare`: ["Ä","a","A","ä","b"].sort(function(a, b) { return a.localeCompare(b); }); ## HOWTO: Dump a stack trace Using a debugger such as Firebug would typically be your best bet, but if you can't for some reason, you can (surprisingly) manipulate the the `stack` property of the "Error" object. Here's a WebOS example: new Error().stack.split('\n').each(function(l) { if (/^\s*at/.match(l)) { Mojo.Log.info(l.replace(/^\s*at\s+/, '')); } }); ## HOWTO: Use the "constructor" property One of the functions of the `new` operator is to set the `constructor` property of the `prototype` object to the constructor function itself. You can use this to create objects of the same "class" as a particular object: Foo = function() { }; foo = new Foo(); foo.constructor === Foo; // true bar = new foo.constructor(); bar instanceof Foo; // true ## HOWTO: Use "apply" with a constructor. You can exploit the fact that you can chain constructors using apply(...) to achieve this, although this requires the creation of a proxy class. The construct() function below lets you do: var f1 = construct(Foo, [2, 3]); // more or less equivalent to var f2 = new Foo(2, 3); The construct() function: function construct(klass, args) { function F() { klass.apply(this, arguments[0]); }; F.prototype = klass.prototype; return new F(args); } Some sample code that uses it: function Foo(a, b) { this.a = a; this.b = b; } Foo.prototype.dump = function() { console.log("a = ", this.a); console.log("b = ", this.b); }; var f = construct(Foo, [7, 9]); f.dump(); Via (Stackoverflow)[http://stackoverflow.com/questions/1959247/javascript-apply-on-constructor-throwing-malformed-formal-parameter/2154471#2154471]. It might also be possible to use `bind()` to do something similar; see the [MDC `bind()` documentation](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind#Supplemental). ## HOWTO: Inherit in NodeJS `lib/util.js` exports an `inherits()` function. ## HOWTO: Generate a random string You can get a random 8 digit base-10 string via: (Math.random() + Math.pow(10, -9)).toString().substr(2, 8) (The `Math.pow(10, -9)` ensures the number is padded with zeroes if necessary.)