From 6fb630874412245d130ca17b218bb22bfb84cc30 Mon Sep 17 00:00:00 2001 From: Sam Stephenson Date: Sun, 15 Feb 2009 21:53:12 -0600 Subject: [PATCH 001/733] Update vendor/sprockets so Prototype builds on Windows again --- vendor/sprockets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/sprockets b/vendor/sprockets index 225b17f7e..42cda525d 160000 --- a/vendor/sprockets +++ b/vendor/sprockets @@ -1 +1 @@ -Subproject commit 225b17f7ee1926d6e9b63a4e2cddbcd2e534ba01 +Subproject commit 42cda525d8e5e6b13fe492ae246960bf140890de From 69adbbbf8f2be60b1c7ce4903ca4c1f8c263241f Mon Sep 17 00:00:00 2001 From: Sam Stephenson Date: Mon, 16 Feb 2009 12:13:13 -0600 Subject: [PATCH 002/733] Update to the latest Sprockets, which trims trailing whitespace from source lines --- vendor/sprockets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/sprockets b/vendor/sprockets index 42cda525d..95aad141d 160000 --- a/vendor/sprockets +++ b/vendor/sprockets @@ -1 +1 @@ -Subproject commit 42cda525d8e5e6b13fe492ae246960bf140890de +Subproject commit 95aad141d4bb31eb8fc36d63e7c682091f06f37f From d3189652a679c57c05ed63633ff57434298e033c Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 18 Feb 2009 10:30:19 -0600 Subject: [PATCH 003/733] Fixed incorrect usage of === operator. [#127 state:resolved] --- src/dom/event.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dom/event.js b/src/dom/event.js index d1922f632..9ab421761 100644 --- a/src/dom/event.js +++ b/src/dom/event.js @@ -403,7 +403,7 @@ document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); } else { document.observe('readystatechange', checkReadyState); - if (window === top) + if (window == top) timer = pollDoScroll.defer(); } From ab1313ea202e0d0bfb7cd0f563b035040710da9b Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 18 Feb 2009 10:34:01 -0600 Subject: [PATCH 004/733] Ensure Element#descendants always returns an array. [#373 state:resolved] --- CHANGELOG | 2 ++ src/dom/dom.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 403bbfc96..d3050b54a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Ensure Element#descendants always returns an array. [#373 state:resolved] (kangax) + * Don't switch fixed position elements to absolute in Element.getDimensions [#543 state:resolved] (James Wheare) * Avoid infinite loops when calling String#sub with empty pattern [#534 state:resolved] (Samuel Lebeau) diff --git a/src/dom/dom.js b/src/dom/dom.js index 2bd17ed82..7e0f0bd56 100644 --- a/src/dom/dom.js +++ b/src/dom/dom.js @@ -189,7 +189,7 @@ Element.Methods = { }, descendants: function(element) { - return $(element).select("*"); + return Element.select(element, "*"); }, firstDescendant: function(element) { From 91b787ae177d5f57919d416955e8d8c85e79019d Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sat, 21 Feb 2009 23:27:18 -0600 Subject: [PATCH 005/733] Ensure the `target` property on events is never undefined in IE. [#383 state:resolved] --- CHANGELOG | 2 ++ src/dom/event.js | 14 +++++++++----- test/functional/event.html | 9 +++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d3050b54a..bd3bcf3e2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Ensure the `target` property on events is never undefined in IE. [#383 state:resolved] (Mathias Karstädt, Diego Perini, Andrew Dupont) + * Ensure Element#descendants always returns an array. [#373 state:resolved] (kangax) * Don't switch fixed position elements to absolute in Element.getDimensions [#543 state:resolved] (James Wheare) diff --git a/src/dom/event.js b/src/dom/event.js index 9ab421761..65e5b0119 100644 --- a/src/dom/event.js +++ b/src/dom/event.js @@ -142,18 +142,22 @@ }); // IE's method for extending events. - Event.extend = function(event) { + Event.extend = function(event, element) { if (!event) return false; if (event._extendedByPrototype) return event; event._extendedByPrototype = Prototype.emptyFunction; var pointer = Event.pointer(event); + + // The optional `element` argument gives us a fallback value for the + // `target` property in case IE doesn't give us through `srcElement`. Object.extend(event, { - target: event.srcElement, + target: event.srcElement || element, relatedTarget: _relatedTarget(event), pageX: pointer.x, pageY: pointer.y }); + return Object.extend(event, methods); }; } else { @@ -171,7 +175,7 @@ // First time we've handled this element. Put it into the cache. CACHE.push(element); registry = Element.retrieve(element, 'prototype_event_registry', $H()); - } + } var respondersForEvent = registry.get(eventName); if (Object.isUndefined()) { @@ -195,13 +199,13 @@ if (event.eventName !== eventName) return false; - Event.extend(event); + Event.extend(event, element); handler.call(element, event); }; } else { // Ordinary event. responder = function(event) { - Event.extend(event); + Event.extend(event, element); handler.call(element, event); }; } diff --git a/test/functional/event.html b/test/functional/event.html index 378b2fb6a..611d5e604 100644 --- a/test/functional/event.html +++ b/test/functional/event.html @@ -229,10 +229,15 @@

Prototype functional tests for the Event module

+

mouseenter test

+ + +

Add unload events

+ + +
+ +
+
+

Prototype JavaScript framework

+
+
+ + + +
+ + <%= @content_for_layout %> + +
+ + + +
+ + + diff --git a/templates/html/namespace.erb b/templates/html/namespace.erb new file mode 100644 index 000000000..ccfecf7ad --- /dev/null +++ b/templates/html/namespace.erb @@ -0,0 +1,157 @@ +<% d = @doc_instance %> + +<% @title = "#{d.full_name} (#{d.type})" %> + +<%= include "partials/breadcrumbs", :object => d %> + +

+ <%= d.type %> <%= d.full_name %> +

+ +<% # Does it have a description? %> + +<% if d.description %> +
+ +
+

Description

+
+ +
+ <%= htmlize(d.description) %> +
+ +
+<% end %> + +<% # Is it a CLASS? %> +<% if @doc_instance.is_a?(Documentation::Klass) %> + + <% if @doc_instance.superklass %> +
+
+

Superclass

+
+ +
+

<%= auto_link_code(d.superklass, false) %>

+
+
+ <% end %> + + <% unless @doc_instance.subklasses.empty? %> +
+
+

Subclasses

+
+ +
+

<%= d.subklasses.map { |s| auto_link_code(s, false) }.join(', ') %>

+
+
+ <% end %> + +<% end %> + +<% # Does it have MIXINS? %> +<% unless @doc_instance.mixins.empty? %> +
+
+

Includes

+
+ +
+

<%= d.mixins.map { |m| auto_link_code(m, false) }.join(', ') %>

+
+
+<% end %> + +<% # Are there related utilities? %> +<% unless @doc_instance.related_utilities.empty? %> +
+
+

Related utilities

+
+ +
+

<%= d.related_utilities.map { |u| auto_link_code(u, false) }.join(', ') %>

+
+
+<% end %> + +<% # List its methods. %> +<% unless d.all_methods.empty? && d.mixins.empty? %> +
+
+

Methods

+
+ +
+
    + <% d.all_methods.each do |method| %> +
  • <%= auto_link_code(method, true, :class => class_names_for(method)) %>
  • + <% end %> +
+ + <% unless @doc_instance.mixins.empty? %> + <% d.mixins.each do |mixin| %> +

Inherited from <%= auto_link(mixin) %>

+
    + <% mixin.all_methods.each do |method| %> +
  • <%= auto_link_code(method, true, :class => class_names_for(method)) %>
  • + <% end %> +
+ <% end %> + <% end %> + + +
+ +
+<% end %> + +<% if d.is_a?(Documentation::Klass) && d.constructor %> +
+
+

Constructor

+
+ +
+
<%= d.constructor.ebnf_expressions.join("\n").strip %>
+ +

<%= htmlize(d.constructor.description) %>

+ +
+ +
+<% end %> + + +<% +types = { + :constants => "Constants", + :klass_methods => "Class methods", + :klass_properties => "Class properties", + :instance_methods => "Instance methods", + :instance_properties => "Instance properties" +} +%> + +<% types.each do |method, title| %> + <% methods = d.send(method) %> + <% unless methods.empty? %> +
+ +
+

<%= title %>

+
+ +
+
    + <%= include "partials/short_description", :collection => methods %> +
+ +
+
+ <% end %> +<% end %> \ No newline at end of file diff --git a/templates/html/partials/breadcrumbs.erb b/templates/html/partials/breadcrumbs.erb new file mode 100644 index 000000000..7e02719d4 --- /dev/null +++ b/templates/html/partials/breadcrumbs.erb @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/templates/html/partials/short_description.erb b/templates/html/partials/short_description.erb new file mode 100644 index 000000000..9c402feb2 --- /dev/null +++ b/templates/html/partials/short_description.erb @@ -0,0 +1,50 @@ +
  • +

    <%= object.name %>

    + + <% if object.is_a?(Documentation::Method) %> + <%= method_synopsis(object) %> + <% unless object.arguments.empty? %> +
      + <% object.arguments.each do |arg| %> +
    • + <%= arg.name %> + <% unless arg.types.empty? %> + (<%= arg.types.map { |t| auto_link_code(t, false) }.join(' | ') %>) + <% end %> + <%= ' – ' + arg.description unless arg.description.empty? %> +
    • + <% end %> +
    + <% end %> + <% end %> + + + + + <%= htmlize(object.description) %> + + <% # Does it have an alias? %> + <% unless object.aliases.empty? %> +

    Aliased as: <%= object.aliases.map { |a| auto_link_code(a, false) }.join(', ') %>

    + <% end %> + + <% # Is it an alias of something else? %> + <% if object.alias? %> +

    Alias of: <%= auto_link_code(object.alias_of, false) %>

    + <% end %> + + <% # Is it related to something? %> + <% if object.is_a?(Documentation::Utility) && object.related_to %> + + <% end %> + + + <% # Is it methodized? %> + <% if object.is_a?(Documentation::Method) && object.methodized? %> +

    This method can be called either as an instance method or as a generic method. If calling as a generic, pass the instance in as the first argument.

    + <% end %> + + + +
  • diff --git a/templates/html/section.erb b/templates/html/section.erb new file mode 100644 index 000000000..2b7bdc0c5 --- /dev/null +++ b/templates/html/section.erb @@ -0,0 +1,90 @@ +<% @title = "#{@doc_instance.full_name} section" %> +<% section = @doc_instance %> + +<%= include "partials/breadcrumbs", :object => section %> + +

    + Section <%= section.name %> +

    + +
    + +
    +

    Description

    +
    + +
    + <%= htmlize(section.description) %> +
    + +
    + +<% # Iterate over the items in this section. %> + +<% utilities = section.utilities %> +<% unless utilities.empty? %> + +
    +
    +

    Utilities

    +
    + +
    +
      + <% utilities.each do |utility| %> +
    • <%= auto_link_code(utility) %>
    • + <% end %> +
    +
    +
    + +<% end %> + +<% namespaces = section.namespaces %> +<% unless namespaces.empty? %> + +
    +
    +

    Namespaces

    +
    + +
    +
      + <% namespaces.each do |namespace| %> +
    • <%= auto_link_code(namespace) %>
    • + <% end %> +
    +
    +
    + +<% end %> + +<% klasses = section.klasses %> +<% unless klasses.empty? %> + +
    + +
    +

    Classes

    +
    + +
    +
      + <% klasses.each do |klass| %> +
    • +

      + <%= klass.full_name %> +

      + + <% unless klass.short_description.nil? %> +

      <%= htmlize(klass.short_description) %>

      + <% end %> + +
    • + <% end %> +
    +
    + +
    + +<% end %> \ No newline at end of file diff --git a/templates/html/utility.erb b/templates/html/utility.erb new file mode 100644 index 000000000..3ffc98d24 --- /dev/null +++ b/templates/html/utility.erb @@ -0,0 +1,21 @@ +<% d = @doc_instance %> + +<% @title = "#{@doc_instance.full_name} utility" %> + +<%= include "partials/breadcrumbs", :object => d %> + +

    + utility <%= @doc_instance.name %> +

    + +
    +
    +

    Description

    +
    + +
    +
      + <%= include "partials/short_description", :collection => [@doc_instance] %> +
    +
    +
    \ No newline at end of file From 8c2af9bd66cba2f8546c3f46c42a45e167b37e0e Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Fri, 6 Mar 2009 15:41:11 -0600 Subject: [PATCH 037/733] Descriptions of all the classes/namespaces in the "Language" section. --- src/lang/array.js | 87 ++++++++++++++++++++++++++- src/lang/date.js | 5 +- src/lang/hash.js | 30 ++++++++-- src/lang/number.js | 11 ++++ src/lang/object.js | 7 +++ src/lang/periodical_executer.js | 23 ++++--- src/lang/range.js | 16 +++++ src/lang/regexp.js | 2 + src/lang/string.js | 8 +++ src/lang/template.js | 102 ++++++++++++++++++++++++++++++++ 10 files changed, 270 insertions(+), 21 deletions(-) diff --git a/src/lang/array.js b/src/lang/array.js index ffe3ee990..7855ad622 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 e9759de49..30abdf833 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 744167397..e4391cdd8 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 dd41dae8f..d56b68ce6 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 6d5122c36..68b89bccb 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 9d18d53a5..266f32474 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 36362e30a..8affa8493 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 bf01c431b..4b1b7ce8d 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 e378ce8f3..beaad091f 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 160351879..5d06e3d6f 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({ /** From 449e532f9a5b75b2e5fd5a4ad8a8b05c4a017e57 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sat, 7 Mar 2009 15:43:20 -0600 Subject: [PATCH 038/733] Add PDoc for most of Ajax section. --- src/ajax.js | 109 +++++++++++++++++++++++++++++++++++++++++ src/ajax/ajax.js | 10 ++++ src/ajax/base.js | 1 + src/ajax/request.js | 101 +++++++++++++++++++++++++++++++++++++- src/ajax/responders.js | 87 ++++++++++++++++++++++++++++++++ src/ajax/response.js | 97 ++++++++++++++++++++++++++++++++++++ src/ajax/updater.js | 28 +++++++++++ 7 files changed, 432 insertions(+), 1 deletion(-) diff --git a/src/ajax.js b/src/ajax.js index 98cf97563..2771fd836 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -1,3 +1,112 @@ +/** + * == Ajax == + * + * Prototype's APIs around the `XmlHttpRequest` object. + * + * The Prototype framework enables you to deal with Ajax calls in a manner that is + * both easy and compatible with all modern browsers. + * + * Actual requests are made by creating instances of [[Ajax.Request]]. + * + *

    Request headers

    + * + * The following headers are sent with all Ajax requests (and can be + * overridden with the `requestHeaders` option described below): + * + * * `X-Requested-With` is set to `XMLHttpRequest`. + * * `X-Prototype-Version` is set to Prototype's current version (e.g., + * `1.6.0.3`). + * * `Accept` is set to `text/javascript, text/html, application/xml, + * text/xml, * / *` + * * `Content-type` is automatically determined based on the `contentType` + * and `encoding` options. + * + *

    Ajax options

    + * + * All Ajax classes share a common set of _options_ and _callbacks_. + * Callbacks are called at various points in the life-cycle of a request, and + * always feature the same list of arguments. + * + *
    Common options
    + * + * * `asynchronous` ([[Boolean]]; default `true`): Determines whether + * `XMLHttpRequest` is used asynchronously or not. Synchronous usage is + * seriously discouraged — it halts all script execution for the duration of + * the request _and_ blocks the browser UI. + * * `contentType` ([[String]]; default `application/x-www-form-urlencoded`): + * The `Content-type` header for your request. Change this header if you + * want to send data in another format (like XML). + * * `encoding` ([[String]]; default `UTF-8`): The encoding for the contents + * of your request. It is best left as-is, but should weird encoding issues + * arise, you may have to tweak this. + * * `method` ([[String]]; default `post`): The HTTP method to use for the + * request. The other common possibility is `get`. Abiding by Rails + * conventions, Prototype also reacts to other HTTP verbs (such as `put` and + * `delete`) by submitting via `post` and adding a extra `_method` parameter + * with the originally-requested method. + * * `parameters` ([[String]]): The parameters for the request, which will be + * encoded into the URL for a `get` method, or into the request body for the + * other methods. This can be provided either as a URL-encoded string, a + * [[Hash]], or a plain [[Object]]. + * * `postBody` ([[String]]): Specific contents for the request body on a + * `post` method. If it is not provided, the contents of the `parameters` + * option will be used instead. + * * `requestHeaders` ([[Object]]): A set of key-value pairs, with properties + * representing header names. + * * `evalJS` ([[Boolean]] | [[String]]; default `true`): Automatically `eval`s + * the content of [[Ajax.Response#responseText]] and populates + * [[Ajax.Response#responseJSON]] with it if the `Content-type` returned by + * the server is set to `application/json`. If the request doesn't obey + * same-origin policy, the content is sanitized before evaluation. If you + * need to force evalutation, pass `'force'`. To prevent it altogether, pass + * `false`. + * * `sanitizeJSON` ([[Boolean]]; default is `false` for same-origin requests, + * `true` otherwise): Sanitizes the contents of + * [[Ajax.Response#responseText]] before evaluating it. + * + *

    Common callbacks

    + * + * When used on individual instances, all callbacks (except `onException`) are + * invoked with two parameters: the `XMLHttpRequest` object and the result of + * evaluating the `X-JSON` response header, if any (can be `null`). + * + * For another way of describing their chronological order and which callbacks + * are mutually exclusive, see [[Ajax.Request]]. + * + * * `onCreate`: Triggered when the [[Ajax.Request]] object is initialized. + * This is _after_ the parameters and the URL have been processed, but + * _before_ opening the connection via the XHR object. + * * `onUninitialized` (*Not guaranteed*): Invoked just after the XHR object + * is created. + * * `onLoading` (*Not guaranteed*): Triggered when the underlying XHR object + * is being setup, and its connection opened. + * * `onLoaded` (*Not guaranteed*): Triggered once the underlying XHR object + * is setup, the connection is open, and it is ready to send its actual + * request. + * * `onInteractive` (*Not guaranteed*): Triggered whenever the requester + * receives a part of the response (but not the final part), should it + * be sent in several packets. + * * `onSuccess`: Invoked when a request completes and its status code is + * `undefined` or belongs in the `2xy` family. This is skipped if a + * code-specific callback is defined (e.g., `on200`), and happens _before_ + * `onComplete`. + * * `onFailure`: Invoked when a request completes and its status code exists + * but _is not_ in the `2xy` family. This is skipped if a code-specific + * callback is defined (e.g. `on403`), and happens _before_ `onComplete`. + * * `onXYZ` (_with `XYZ` representing any HTTP status code_): Invoked just + * after the response is complete _if_ the status code is the exact code + * used in the callback name. _Prevents_ execution of `onSuccess` and + * `onFailure`. Happens _before_ `onComplete`. + * * `onException`: Triggered whenever an XHR error arises. Has a custom + * signature: the first argument is the requester (i.e. an [[Ajax.Request]] + * instance), and the second is the exception object. + * * `onComplete`: Triggered at the _very end_ of a request's life-cycle, after + * the request completes, status-specific callbacks are called, and possible + * automatic behaviors are processed. Guaranteed to run regardless of what + * happened during the request. + * +**/ + //= require "ajax/ajax" //= require "ajax/responders" //= require "ajax/base" diff --git a/src/ajax/ajax.js b/src/ajax/ajax.js index 4895a1003..d8174f29b 100644 --- a/src/ajax/ajax.js +++ b/src/ajax/ajax.js @@ -1,3 +1,7 @@ +/** section: Ajax + * Ajax +**/ + var Ajax = { getTransport: function() { return Try.these( @@ -7,5 +11,11 @@ var Ajax = { ) || false; }, + /** + * Ajax.activeRequestCount -> Number + * + * Represents the number of active XHR requests triggered through + * [[Ajax.Request]], [[Ajax.Updater]], or [[Ajax.PeriodicalUpdater]]. + **/ activeRequestCount: 0 }; diff --git a/src/ajax/base.js b/src/ajax/base.js index b6413db8e..0be66bcf4 100644 --- a/src/ajax/base.js +++ b/src/ajax/base.js @@ -1,3 +1,4 @@ +// Abstract class; does not need documentation. Ajax.Base = Class.create({ initialize: function(options) { this.options = { diff --git a/src/ajax/request.js b/src/ajax/request.js index 6937b5df9..d09d53d6a 100644 --- a/src/ajax/request.js +++ b/src/ajax/request.js @@ -1,6 +1,92 @@ +/** section: Ajax + * class Ajax.Request + * + * Initiates and processes an Ajax request. + * + * `Ajax.Request` is a general-purpose class for making HTTP requests. + * + *

    Automatic JavaScript response evaluation

    + * + * If an Ajax request follows the _same-origin policy_ **and** its response + * has a JavaScript-related `Content-type`, the content of the `responseText` + * property will automatically be passed to `eval`. + * + * In other words: you don't even need to provide a callback to leverage + * pure-JavaScript AJAX responses. This is the convention that drives Rails's + * RJS. + * + * The list of JavaScript-related MIME-types handled by Prototype is: + * + * * `application/ecmascript` + * * `application/javascript` + * * `application/x-ecmascript` + * * `application/x-javascript` + * * `text/ecmascript` + * * `text/javascript` + * * `text/x-ecmascript` + * * `text/x-javascript` + * + * The MIME-type string is examined in a case-insensitive manner. + * + *

    Methods you may find useful

    + * + * Instances of the `Request` object provide several methods that can come in + * handy in your callback functions, especially once the request is complete. + * + *
    Is the response a successful one?
    + * + * The [[Ajax.Request#success]] method examines the XHR object's `status` + * property and follows general HTTP guidelines: unknown status is deemed + * successful, as is the whole `2xy` status code family. It's a generally + * better way of testing your response than the usual + * `200 == transport.status`. + * + *
    Getting HTTP response headers
    + * + * While you can obtain response headers from the XHR object using its + * `getResponseHeader` method, this makes for verbose code, and several + * implementations raise an exception when the header is not found. To make + * this easier, you can use the [[Ajax.Response#getHeader]] method, which + * delegates to the longer version and returns `null` if an exception occurs: + * + * new Ajax.Request('/your/url', { + * onSuccess: function(response) { + * // Note how we brace against null values + * if ((response.getHeader('Server') || '').match(/Apache/)) + * ++gApacheCount; + * // Remainder of the code + * } + * }); + * + *
    Evaluating JSON headers
    + * + * Some backends will return JSON not as response text, but in the `X-JSON` + * header. In this case, you don't even need to evaluate the returned JSON + * yourself, as Prototype automatically does so. It passes the result as the + * `headerJSON` property of the [[Ajax.Response]] object. Note that if there + * is no such header — or its contents are invalid — `headerJSON` will be set + * to `null`. + * + * new Ajax.Request('/your/url', { + * onSuccess: function(transport) { + * transport.headerJSON + * } + * }); +**/ Ajax.Request = Class.create(Ajax.Base, { _complete: false, + /** + * new Ajax.Request(url[, options]) + * - url (String): The URL to fetch. When the _same-origin_ policy is in + * effect (as it is in most cases), `url` **must** be a relative URL or an + * absolute URL that starts with a slash (i.e., it must not begin with + * `http`). + * - options (Object): Configuration for the request. See the + * [[Ajax section]] for more information. + * + * Creates a new `Ajax.Request`. + **/ initialize: function($super, url, options) { $super(options); this.transport = Ajax.getTransport(); @@ -95,6 +181,11 @@ Ajax.Request = Class.create(Ajax.Base, { this.transport.setRequestHeader(name, headers[name]); }, + /** + * Ajax.Request.success() -> Boolean + * + * Tests whether the request was successful. + **/ success: function() { var status = this.getStatus(); return !status || (status >= 200 && status < 300); @@ -148,10 +239,18 @@ Ajax.Request = Class.create(Ajax.Base, { })); }, + /** + * Ajax.Request.getHeader(name) -> String | null + * - name (String): The name of an HTTP header that may have been part of + * the response. + * + * Returns the value of the given response header, or `null` if that header + * was not found. + **/ getHeader: function(name) { try { return this.transport.getResponseHeader(name) || null; - } catch (e) { return null } + } catch (e) { return null; } }, evalResponse: function() { diff --git a/src/ajax/responders.js b/src/ajax/responders.js index a317a9031..80a8e3733 100644 --- a/src/ajax/responders.js +++ b/src/ajax/responders.js @@ -1,3 +1,71 @@ +/** section: Ajax + * Ajax.Responders + * + * A repository of global listeners notified about every step of + * Prototype-based Ajax requests. + * + * Sometimes, you need to provide generic behaviors over all Ajax operations + * happening on the page (through [[Ajax.Request]], [[Ajax.Updater]] or + * [[Ajax.PeriodicalUpdater]]). + * + * For instance, you might want to automatically show an indicator when an + * Ajax request is ongoing, and hide it when none are. You may well want to + * factor out exception handling as well, logging those somewhere on the page + * in a custom fashion. The possibilities are myriad. + * + * To achieve this, Prototype provides `Ajax.Responders`, which lets you + * register (and, if you wish, unregister later) _responders_, which are + * objects with specially-named methods. These names come from a set of + * general callbacks corresponding to different points in time (or outcomes) + * of an Ajax request's life cycle. + * + * For instance, Prototype automatically registers a responder that maintains + * a nifty variable: [[Ajax.activeRequestCount]]. This represents, at a given + * time, the number of currently active Ajax requests — by monitoring their + * `onCreate` and `onComplete` events. The code for this is fairly simple: + * + * Ajax.Responders.register({ + * onCreate: function() { + * Ajax.activeRequestCount++; + * }, + * onComplete: function() { + * Ajax.activeRequestCount--; + * } + * }); + * + *

    Responder callbacks

    + * + * The callbacks for responders are similar to the callbacks described in + * the [[Ajax section]], but take a different signature. They're invoked with + * three parameters: the requester object (i.e., the corresponding "instance" + * of [[Ajax.Request]]), the `XMLHttpRequest` object, and the result of + * evaluating the `X-JSON` response header, if any (can be `null`). They also + * execute in the context of the responder, bound to the `this` reference. + * + * * `onCreate`: Triggered whenever a requester object from the `Ajax` + * namespace is created, after its parameters are adjusted and before its + * XHR connection is opened. This takes *two* arguments: the requester + * object and the underlying XHR object. + * * `onUninitialized` (*Not guaranteed*): Invoked just after the XHR object + * is created. + * * `onLoading` (*Not guaranteed*): Triggered when the underlying XHR object + * is being setup, and its connection opened. + * * `onLoaded` (*Not guaranteed*): Triggered once the underlying XHR object + * is setup, the connection is open, and it is ready to send its actual + * request. + * * `onInteractive` (*Not guaranteed*): Triggered whenever the requester + * receives a part of the response (but not the final part), should it + * be sent in several packets. + * * `onException`: Triggered whenever an XHR error arises. Has a custom + * signature: the first argument is the requester (i.e. an [[Ajax.Request]] + * instance), and the second is the exception object. + * * `onComplete`: Triggered at the _very end_ of a request's life-cycle, after + * the request completes, status-specific callbacks are called, and possible + * automatic behaviors are processed. Guaranteed to run regardless of what + * happened during the request. + * +**/ + Ajax.Responders = { responders: [], @@ -5,11 +73,30 @@ Ajax.Responders = { this.responders._each(iterator); }, + /** + * Ajax.Responders.register(responder) -> undefined + * - responder (Object): A list of functions with keys corresponding to the + * names of possible callbacks. + * + * Add a group of responders to all Ajax requests. + **/ register: function(responder) { if (!this.include(responder)) this.responders.push(responder); }, + /** + * Ajax.Responders.unregister(responder) -> undefined + * - responder (Object): A list of functions with keys corresponding to the + * names of possible callbacks. + * + * Remove a previously-added group of responders. + * + * As always, unregistering something requires you to use the very same + * object you used at registration. If you plan to use `unregister`, be sure + * to assign your responder to a _variable_ before passing it into + * [[Ajax.Responders#register]] — don't pass it an object literal. + **/ unregister: function(responder) { this.responders = this.responders.without(responder); }, diff --git a/src/ajax/response.js b/src/ajax/response.js index c8bc2f856..62244262d 100644 --- a/src/ajax/response.js +++ b/src/ajax/response.js @@ -1,4 +1,64 @@ +/** section: Ajax + * class Ajax.Response + * + * A wrapper class around `XmlHttpRequest` for dealing with HTTP responses + * of Ajax requests. + * + * An instance of `Ajax.Response` is passed as the first argument of all Ajax + * requests' callbacks. You _will not_ need to create instances of + * `Ajax.Response` yourself. +**/ + +/** + * Ajax.Response#readyState -> Number + * + * The request’s current state. + * + * `0` corresponds to `"Uninitialized"`, `1` to `"Loading"`, `2` to + * `"Loaded"`, `3` to `"Interactive"`, and `4` to `"Complete"`. +**/ + +/** + * Ajax.Response#responseText -> String + * + * The text body of the response. +**/ + +/** + * Ajax.Response#responseXML -> document | null + * + * The XML body of the response if the `Content-type` of the request is set + * to `application/xml`; `null` otherwise. +**/ + +/** + * Ajax.Response#responseJSON -> Object | Array | null + * + * The JSON body of the response if the `Content-type` of the request is set + * to `application/json`; `null` otherwise. +**/ + +/** + * Ajax.Response#headerJSON -> Object | Array | null + * + * Auto-evaluated content of the `X-JSON` header if present; `null` otherwise. +**/ + +/** + * Ajax.Response#request -> Ajax.Request | Ajax.Updater + * + * The request object itself (an instance of [[Ajax.Request]] or + * [[Ajax.Updater]]). +**/ + +/** + * Ajax.Response#transport -> XmlHttpRequest + * + * The native `XmlHttpRequest` object itself. +**/ + Ajax.Response = Class.create({ + // Don't document the constructor; should never be manually instantiated. initialize: function(request){ this.request = request; var transport = this.transport = request.transport, @@ -18,7 +78,18 @@ Ajax.Response = Class.create({ } }, + /** + * Ajax.Response#status -> Number + * + * The HTTP status code sent by the server. + **/ status: 0, + + /** + * Ajax.Response#statusText -> String + * + * The HTTP status text sent by the server. + **/ statusText: '', getStatus: Ajax.Request.prototype.getStatus, @@ -29,18 +100,44 @@ Ajax.Response = Class.create({ } catch (e) { return '' } }, + /** + * Ajax.Response#getHeader(name) -> String | null + * + * See [[Ajax.Request#getHeader]]. + **/ getHeader: Ajax.Request.prototype.getHeader, + /** + * Ajax.Response#getAllHeaders() -> String | null + * + * Returns a string containing all headers separated by line breaks. _Does + * not__ throw errors if no headers are present the way its native + * counterpart does. + **/ getAllHeaders: function() { try { return this.getAllResponseHeaders(); } catch (e) { return null } }, + /** + * Ajax.Response.getResponseHeader(name) -> String + * + * Returns the value of the requested header if present; throws an error + * otherwise. This is just a wrapper around the `XmlHttpRequest` method of + * the same name. + **/ getResponseHeader: function(name) { return this.transport.getResponseHeader(name); }, + /** + * Ajax.Response.getAllResponseHeaders() -> String + * + * Returns a string containing all headers separated by line breaks; throws + * an error if no headers exist. This is just a wrapper around the + * `XmlHttpRequest` method of the same name. + **/ getAllResponseHeaders: function() { return this.transport.getAllResponseHeaders(); }, diff --git a/src/ajax/updater.js b/src/ajax/updater.js index 262c7f6f2..e1efa9897 100644 --- a/src/ajax/updater.js +++ b/src/ajax/updater.js @@ -1,3 +1,31 @@ +/** section: Ajax + * class Ajax.Updater < Ajax.Request + * + * A class that performs an Ajax request and updates a container’s contents + * with the contents of the response. + * + * `Ajax.Updater` is a subclass of [[Ajax.Request]] built for a common + * use-case. + * + *

    Example

    + * + * new Ajax.Updater('items', '/items', { + * parameters: { text: $F('text') } + * }); + * + * This example will make a request to the URL `/items` (with the given + * parameters); it will then replace the contents of the element with the ID + * of `items` with whatever response it receives. + * + * + * +**/ + + + + + + Ajax.Updater = Class.create(Ajax.Request, { initialize: function($super, container, url, options) { this.container = { From 0f5c9bfcc54c0de0239307ec42dd3662a5805048 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sat, 7 Mar 2009 15:44:12 -0600 Subject: [PATCH 039/733] Updates to PDoc in DOM section. --- src/dom.js | 15 +++++++++++++++ src/dom/form.js | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/dom.js b/src/dom.js index 303e6ebb4..97722309b 100644 --- a/src/dom.js +++ b/src/dom.js @@ -2,6 +2,21 @@ * == DOM == * Extensions to DOM elements, plus other utilities for DOM traversal * and modification. + * + * Prototype's DOM extensions represent a large portion of where you'll spend + * your time. Prototype adds many convenience methods to elements returned by + * the [[$]] function. For instance, you can write + * + * $('comments').addClassName('active').show(); + * + * to get the element with the ID of `comments`, add a class name to it, and + * show it (if it was previously hidden). + * + * In other words, Prototype adds "instance" methods to DOM nodes. This is + * made possible by direct extension of the backing DOM objects (in browsers + * that support it) and by manual extension of individual nodes (in browsers + * that do not). + * **/ diff --git a/src/dom/form.js b/src/dom/form.js index affb71d18..ed03704a8 100644 --- a/src/dom/form.js +++ b/src/dom/form.js @@ -334,7 +334,7 @@ Form.Element.Methods = { var Field = Form.Element; -/** section: DOM, alias of: Form.Element.getValue +/** section: DOM, related to: Form * $F(element) -> String | Array **/ var $F = Form.Element.Methods.getValue; From deb3df525e9f6d9e7ab311e0a93e48a6ad51be63 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sat, 7 Mar 2009 15:44:50 -0600 Subject: [PATCH 040/733] Change some PDoc characters to HTML entities so that we don't confuse Sprockets. --- src/lang/template.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/lang/template.js b/src/lang/template.js index 5d06e3d6f..83d7ab344 100644 --- a/src/lang/template.js +++ b/src/lang/template.js @@ -18,7 +18,6 @@ * 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}.'); @@ -74,8 +73,6 @@ * 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 @@ -83,14 +80,15 @@ * 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 `<%= %>` + * together a template that uses a syntax similar to the ubiquitous `<&= %>` * constructs: * - * // matches symbols like '<%= field %>' + * // matches symbols like '<&= field %>' * var syntax = /(^|.|\r|\n)(\<%=\s*(\w+)\s*%\>)/; * * var t = new Template( - * '
    Name: <%= name %>, Age: <%=age%>
    ', syntax); + * '
    Name: <&= name %>, Age: <&=age%>
    ', + * syntax); * t.evaluate( {name: 'John Smith', age: 26} ); * // ->
    Name: John Smith, Age: 26
    * From 15b936af9138528529e7de04e4a680ff6ef99f95 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sat, 7 Mar 2009 15:45:22 -0600 Subject: [PATCH 041/733] Changes to PDoc template to fix issues relating to sections. --- templates/html/assets/stylesheets/api.css | 18 ++++++++++++++++++ templates/html/helpers.rb | 20 +++++++++++++++++++- templates/html/index.erb | 6 ++++-- templates/html/layout.erb | 17 +++++++++++++++-- templates/html/namespace.erb | 2 +- templates/html/section.erb | 13 +++++++++++-- 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/templates/html/assets/stylesheets/api.css b/templates/html/assets/stylesheets/api.css index 55c88f5cf..2b2530a03 100644 --- a/templates/html/assets/stylesheets/api.css +++ b/templates/html/assets/stylesheets/api.css @@ -61,6 +61,24 @@ div#footer { text-decoration: underline; border: 0; } + + div.copyright, + div.credits { + width: 360px; + float: left; + } + + div.copyright .cc { + width: 115px; + margin-right: 5px; + text-align: center; + float: left; + } + + div.copyright .copyright-about { + width: 235px; + float: left; + } .page-title span.type { diff --git a/templates/html/helpers.rb b/templates/html/helpers.rb index c9a74f9d6..1c9bb7ed4 100644 --- a/templates/html/helpers.rb +++ b/templates/html/helpers.rb @@ -60,11 +60,23 @@ def path_prefix end def path_to(obj) - path = path_prefix << [obj.section.name].concat(obj.namespace_string.downcase.split('.')).join("/") + return path_to_section(obj) if obj.is_a?(Documentation::Section) + path = path_prefix << [obj.section.name.downcase].concat(obj.namespace_string.downcase.split('.')).join("/") has_own_page?(obj) ? "#{path}/#{obj.id.downcase}.html" : "#{path}.html##{dom_id(obj)}" end + + def path_to_section(obj) + "#{path_prefix}#{obj.id.gsub(/\s/, '_')}.html" + end + + def section_from_name(name) + root.sections.find { |section| section.name == name } + end def auto_link(obj, short = true, attributes = {}) + if obj.is_a?(String) && obj =~ /\ssection$/ + obj = section_from_name(obj.gsub(/\ssection$/, '')) + end obj = root.find_by_name(obj) || obj if obj.is_a?(String) return nil if obj.nil? return obj if obj.is_a?(String) @@ -77,6 +89,12 @@ def auto_link_code(obj, short = true, attributes = {}) end def auto_link_content(content) + content.gsub!(/\[\[([a-zA-Z]+)\s+section\]\]/) do |m| + puts; puts m; puts + result = auto_link(section_from_name($1), false) + puts; puts result; puts + result + end content.gsub(/\[\[([a-zA-Z$\.#]+)(?:\s+([^\]]+))?\]\]/) do |m| if doc_instance = root.find_by_name($1) $2 ? link_to($2, path_to(doc_instance)) : diff --git a/templates/html/index.erb b/templates/html/index.erb index a7aa4934e..3164a7e57 100644 --- a/templates/html/index.erb +++ b/templates/html/index.erb @@ -16,8 +16,10 @@
      <% @root.sections.each do |section| %>
    • -

      <%= auto_link(section.name) %>

      -

      <%= section.short_description %>

      +

      + <%= section.name %> +

      +

      <%= htmlize(section.short_description) %>

    • <% end %>
    diff --git a/templates/html/layout.erb b/templates/html/layout.erb index 6227d0e86..fe0c045f5 100644 --- a/templates/html/layout.erb +++ b/templates/html/layout.erb @@ -52,8 +52,21 @@