diff --git a/src/lang/array.js b/src/lang/array.js
index ffe3ee9..7855ad6 100644
--- a/src/lang/array.js
+++ b/src/lang/array.js
@@ -1,4 +1,4 @@
-/** section: Language, alias of: Array.from
+/** section: Language, alias of: Array.from, related to: Array
* $A(iterable) -> Array
*
* Accepts an array-like collection (anything with numeric indices) and returns
@@ -29,7 +29,7 @@ if (Prototype.Browser.WebKit) {
};
}
-/** section: Language
+/** section: Language, related to: Array
* $w(string) -> Array
* - string (String): A string with zero or more spaces.
*
@@ -43,11 +43,94 @@ function $w(string) {
return string ? string.split(/\s+/) : [];
}
+/** alias of: $A
+ * Array.from(iterable) -> Array
+**/
Array.from = $A;
/** section: Language
* class Array
+ *
+ * Prototype extends all native JavaScript arrays with quite a few powerful
+ * methods.
+ *
+ * This is done in two ways:
+ *
+ * * It mixes in the [[Enumerable]] module, which brings a ton of methods in
+ * already.
+ * * It adds quite a few extra methods, which are documented in this section.
+ *
+ * With Prototype, arrays become much, much more than the trivial objects we
+ * used to manipulate, limiting ourselves to using their `length` property and
+ * their `[]` indexing operator. They become very powerful objects that
+ * greatly simplify the code for 99% of the common use cases involving them.
+ *
+ *
Why you should stop using for…in to iterate
+ *
+ * Many JavaScript authors have been misled into using the `for…in` JavaScript
+ * construct to loop over array elements. This kind of code just won’t work
+ * with Prototype.
+ *
+ * The ECMA 262 standard, which defines ECMAScript 3rd edition, supposedly
+ * implemented by all major browsers including MSIE, defines ten methods
+ * on Array (§15.4.4), including nice methods like `concat`, `join`, `pop`, and
+ * `push`.
+ *
+ * This same standard explicitely defines that the `for…in` construct (§12.6.4)
+ * exists to enumerate the properties of the object appearing on the right side
+ * of the `in` keyword. Only properties specifically marked as _non-enumerable_
+ * are ignored by such a loop. By default, the `prototype` and `length`
+ * properties are so marked, which prevents you from enumerating over array
+ * methods when using for…in. This comfort led developers to use `for…in` as a
+ * shortcut for indexing loops, when it is not its actual purpose.
+ *
+ * However, Prototype has no way to mark the methods it adds to
+ * `Array.prototype` as non-enumerable. Therefore, using `for…in` on arrays
+ * when using Prototype will enumerate all extended methods as well, such as
+ * those coming from the [[Enumerable]] module, and those Prototype puts in the
+ * Array namespace (listed further below).
+ *
+ * What you should use instead
+ *
+ * You can revert to vanilla loops:
+ *
+ * for (var index = 0; index < myArray.length; ++index) {
+ * var item = myArray[index];
+ * // Your code working on item here...
+ * }
+ *
+ * Or you can use iterators, such as [[Array#each]]:
+ *
+ * myArray.each(function(item) {
+ * // Your code working on item here...
+ * });
+ *
+ *
+ * The inability to use `for...in` on arrays is not much of a burden: as you’ll
+ * see, most of what you used to loop over arrays for can be concisely done
+ * using the new methods provided by Array or the mixed-in [[Enumerable]]
+ * module. So manual loops should be fairly rare.
+ *
+ *
+ * A note on performance
+ *
+ * Should you have a very large array, using iterators with lexical closures
+ * (anonymous functions that you pass to the iterators and that get invoked at
+ * every loop iteration) in methods like [[Array#each]] — _or_ relying on
+ * repetitive array construction (such as uniq), may yield unsatisfactory
+ * performance. In such cases, you’re better off writing manual indexing loops,
+ * but take care then to cache the length property and use the prefix `++`
+ * operator:
+ *
+ * // Custom loop with cached length property: maximum full-loop
+ * // performance on very large arrays!
+ * for (var index = 0, len = myArray.length; index < len; ++index) {
+ * var item = myArray[index];
+ * // Your code working on item here...
+ * }
+ *
**/
+
(function() {
var arrayProto = Array.prototype,
slice = arrayProto.slice,
diff --git a/src/lang/date.js b/src/lang/date.js
index e9759de..30abdf8 100644
--- a/src/lang/date.js
+++ b/src/lang/date.js
@@ -1,12 +1,13 @@
/** section: Language
* class Date
+ *
+ * Extensions to the built-in `Date` object.
**/
/**
- * Date#toJSON -> String
+ * Date#toJSON() -> String
*
* Produces a string representation of the date in ISO 8601 format.
- *
**/
Date.prototype.toJSON = function() {
return '"' + this.getUTCFullYear() + '-' +
diff --git a/src/lang/hash.js b/src/lang/hash.js
index 7441673..e4391cd 100644
--- a/src/lang/hash.js
+++ b/src/lang/hash.js
@@ -1,9 +1,11 @@
-/** section: Language
+/** section: Language, related to: Hash
* $H([object]) -> Hash
*
- * Creates a Hash (which is synonymous to “map” or “associative array” for our purposes).
- * A convenience wrapper around the Hash constructor, with a safeguard that lets you pass
- * an existing Hash object and get it back untouched (instead of uselessly cloning it).
+ * Creates a `Hash`.
+ *
+ * `$H` is a convenience wrapper around the Hash constructor, with a safeguard
+ * that lets you pass an existing Hash object and get it back untouched
+ * (instead of uselessly cloning it).
**/
function $H(object) {
return new Hash(object);
@@ -11,6 +13,24 @@ function $H(object) {
/** section: Language
* class Hash
+ *
+ * A set of key/value pairs.
+ *
+ * `Hash` can be thought of as an associative array, binding unique keys to
+ * values (which are not necessarily unique), though it can not guarantee
+ * consistent order its elements when iterating. Because of the nature of
+ * JavaScript, every object is in fact a hash; but `Hash` adds a number of
+ * methods that let you enumerate keys and values, iterate over key/value
+ * pairs, merge two hashes together, and much more.
+ *
+ * Creating a hash
+ *
+ * There are two ways to construct a Hash instance: the first is regular
+ * JavaScript object instantiation with the `new` keyword, and the second is
+ * using the [[$H]] function. There is one difference between them: if a `Hash`
+ * is passed to `$H`, it will be returned as-is, wherease the same hash passed
+ * to `new Hash` will be _cloned_ instead.
+ *
**/
var Hash = Class.create(Enumerable, (function() {
/**
@@ -35,7 +55,7 @@ var Hash = Class.create(Enumerable, (function() {
/**
* Hash#set(key, value) -> value
*
- * Sets the hash’s `key` property to value and returns value.
+ * Sets the hash’s `key` property to `value` and returns `value`.
**/
function set(key, value) {
return this._object[key] = value;
diff --git a/src/lang/number.js b/src/lang/number.js
index dd41dae..d56b68c 100644
--- a/src/lang/number.js
+++ b/src/lang/number.js
@@ -1,5 +1,16 @@
/** section: Language
* class Number
+ *
+ * Extensions to the built-in `Number` object.
+ *
+ * Prototype extends native JavaScript numbers in order to provide:
+ *
+ * * [[ObjectRange]] compatibility, through [[Number#succ]].
+ * * Ruby-like numerical loops with [[Number#times]].
+ * * Simple utility methods such as [[Number#toColorPart]] and
+ * [[Number#toPaddedString]].
+ * * Instance-method aliases of many functions in the `Math` namespace.
+ *
**/
Object.extend(Number.prototype, (function() {
/**
diff --git a/src/lang/object.js b/src/lang/object.js
index 6d5122c..68b89bc 100644
--- a/src/lang/object.js
+++ b/src/lang/object.js
@@ -1,5 +1,12 @@
/** section: Language
* class Object
+ *
+ * Extensions to the built-in `Object` object.
+ *
+ * Because it is dangerous and invasive to augment `Object.prototype` (i.e.,
+ * add instance methods to objects), all these methods are static methods that
+ * take an `Object` as their first parameter.
+ *
**/
(function() {
diff --git a/src/lang/periodical_executer.js b/src/lang/periodical_executer.js
index 9d18d53..266f324 100644
--- a/src/lang/periodical_executer.js
+++ b/src/lang/periodical_executer.js
@@ -1,5 +1,15 @@
/** section: Language
* class PeriodicalExecuter
+ *
+ * A class that oversees the calling of a particular function periodically.
+ *
+ * `PeriodicalExecuter` shields you from multiple parallel executions of the
+ * `callback` function, should it take longer than the given interval to
+ * execute.
+ *
+ * This is especially useful if you use one to interact with the user at
+ * given intervals (e.g. use a prompt or confirm call): this will avoid
+ * multiple message boxes all waiting to be actioned.
**/
var PeriodicalExecuter = Class.create({
/**
@@ -8,18 +18,7 @@ var PeriodicalExecuter = Class.create({
* - frequency (Number): the amount of time, in sections, to wait in between
* callbacks.
*
- * Creates an object that oversees the calling of a particular function via
- * `window.setInterval`.
- *
- * The only notable advantage provided by `PeriodicalExecuter` is that it
- * shields you against multiple parallel executions of the `callback`
- * function, should it take longer than the given interval to execute (it
- * maintains an internal “running” flag, which is shielded against
- * exceptions in the callback function).
- *
- * This is especially useful if you use one to interact with the user at
- * given intervals (e.g. use a prompt or confirm call): this will avoid
- * multiple message boxes all waiting to be actioned.
+ * Creates an `PeriodicalExecuter`.
**/
initialize: function(callback, frequency) {
this.callback = callback;
diff --git a/src/lang/range.js b/src/lang/range.js
index 36362e3..8affa84 100644
--- a/src/lang/range.js
+++ b/src/lang/range.js
@@ -1,5 +1,21 @@
/** section: Language
* class ObjectRange
+ *
+ * Ranges represent an interval of values. The value type just needs to be
+ * "compatible" — that is, to implement a `succ` method letting us step from
+ * one value to the next (its successor).
+ *
+ * Prototype provides such a method for [[Number]] and [[String]], but you
+ * are (of course) welcome to implement useful semantics in your own objects,
+ * in order to enable ranges based on them.
+ *
+ * `ObjectRange` mixes in [[Enumerable]], which makes ranges very versatile.
+ * It takes care, however, to override the default code for `include`, to
+ * achieve better efficiency.
+ *
+ * While `ObjectRange` does provide a constructor, the preferred way to obtain
+ * a range is to use the [[$R]] utility function, which is strictly equivalent
+ * (only way more concise to use).
**/
/** section: Language
diff --git a/src/lang/regexp.js b/src/lang/regexp.js
index bf01c43..4b1b7ce 100644
--- a/src/lang/regexp.js
+++ b/src/lang/regexp.js
@@ -1,5 +1,7 @@
/** section: Language
* class RegExp
+ *
+ * Extensions to the built-in `RegExp` object.
**/
/** alias of: RegExp#test
diff --git a/src/lang/string.js b/src/lang/string.js
index e378ce8..beaad09 100644
--- a/src/lang/string.js
+++ b/src/lang/string.js
@@ -1,5 +1,13 @@
/** section: Language
* class String
+ *
+ * Extensions to the built-in `String` class.
+ *
+ * Prototype enhances the `String` object with a series of useful methods for
+ * ranging from the trivial to the complex. Tired of stripping trailing
+ * whitespace? Try [[String#strip]]. Want to replace `replace`? Have a look at
+ * [[String#sub]] and [[String#gsub]]. Need to parse a query string? We have
+ * [[String#toQueryParams]].
**/
Object.extend(String, {
/**
diff --git a/src/lang/template.js b/src/lang/template.js
index 1603518..5d06e3d 100644
--- a/src/lang/template.js
+++ b/src/lang/template.js
@@ -1,5 +1,107 @@
/** section: Language
* class Template
+ *
+ * A class for sophisticated string interpolation.
+ *
+ * Any time you have a group of similar objects and you need to produce
+ * formatted output for these objects, maybe inside a loop, you typically
+ * resort to concatenating string literals with the object's fields. There's
+ * nothing wrong with this approach, except that it is hard to visualize the
+ * output immediately just by glancing at the concatenation expression. The
+ * `Template` class provides a much nicer and clearer way of achieving this
+ * formatting.
+ *
+ * Straightforward templates
+ *
+ * The Template class uses a basic formatting syntax, similar to what is used
+ * in Ruby. The templates are created from strings that have embedded symbols
+ * in the form (e.g., `#{fieldName}`) that will be replaced by actual values
+ * when the template is applied (evaluated) to an object.
+ *
+ *
+ * // the template (our formatting expression)
+ * var myTemplate = new Template(
+ * 'The TV show #{title} was created by #{author}.');
+ *
+ * // our data to be formatted by the template
+ * var show = {
+ * title: 'The Simpsons',
+ * author: 'Matt Groening',
+ * network: 'FOX'
+ * };
+ *
+ * // let's format our data
+ * myTemplate.evaluate(show);
+ * // -> "The TV show The Simpsons was created by Matt Groening."
+ *
+ * Templates are meant to be reused
+ *
+ * As the example illustrates, `Template` objects are not tied to specific
+ * data. The data is bound to the template only during the evaluation of the
+ * template, without affecting the template itself. The next example shows the
+ * same template being used with a handful of distinct objects.
+ *
+ *
+ * // creating a few similar objects
+ * var conversion1 = { from: 'meters', to: 'feet', factor: 3.28 };
+ * var conversion2 = { from: 'kilojoules', to: 'BTUs', factor: 0.9478 };
+ * var conversion3 = { from: 'megabytes', to: 'gigabytes', factor: 1024 };
+ *
+ * // the template
+ * var templ = new Template(
+ * 'Multiply by #{factor} to convert from #{from} to #{to}.');
+ *
+ * // let's format each object
+ * [conversion1, conversion2, conversion3].each( function(conv){
+ * templ.evaluate(conv);
+ * });
+ * // -> Multiply by 3.28 to convert from meters to feet.
+ * // -> Multiply by 0.9478 to convert from kilojoules to BTUs.
+ * // -> Multiply by 1024 to convert from megabytes to gigabytes.
+ *
+ * Escape sequence
+ *
+ * There's always the chance that one day you'll need to have a literal in your
+ * template that looks like a symbol, but is not supposed to be replaced. For
+ * these situations there's an escape character: the backslash (`\`).
+ *
+ * // NOTE: you're seeing two backslashes here because the backslash
+ * // is also an escape character in JavaScript strings, so a literal
+ * // backslash is represented by two backslashes.
+ * var t = new Template(
+ * 'in #{lang} we also use the \\#{variable} syntax for templates.');
+ * var data = { lang:'Ruby', variable: '(not used)' };
+ * t.evaluate(data);
+ * // -> in Ruby we also use the #{variable} syntax for templates.
+ *
+ *
+ *
+ * Custom syntaxes
+ *
+ * The default syntax of the template strings will probably be enough for most
+ * scenarios. In the rare occasion where the default Ruby-like syntax is
+ * inadequate, there's a provision for customization. `Template`'s
+ * constructor accepts an optional second argument that is a regular expression
+ * object to match the replaceable symbols in the template string. Let's put
+ * together a template that uses a syntax similar to the ubiquitous `<%= %>`
+ * constructs:
+ *
+ * // matches symbols like '<%= field %>'
+ * var syntax = /(^|.|\r|\n)(\<%=\s*(\w+)\s*%\>)/;
+ *
+ * var t = new Template(
+ * 'Name: <%= name %>, Age: <%=age%>
', syntax);
+ * t.evaluate( {name: 'John Smith', age: 26} );
+ * // -> Name: John Smith, Age: 26
+ *
+ * There are important constraints to any custom syntax. Any syntax must
+ * provide at least three groupings in the regular expression. The first
+ * grouping is to capture what comes before the symbol, to detect the backslash
+ * escape character (no, you cannot use a different character). The second
+ * grouping captures the entire symbol and will be completely replaced upon
+ * evaluation. Lastly, the third required grouping captures the name of the
+ * field inside the symbol.
+ *
**/
var Template = Class.create({
/**