resolving merge

This commit is contained in:
Jeremy Ashkenas
2012-04-02 13:06:44 -04:00
6 changed files with 197 additions and 120 deletions

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1"> <meta http-equiv="X-UA-Compatible" content="chrome=1">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<title>Underscore.js</title> <title>Underscore.js</title>
<style> <style>
body { body {
@@ -11,7 +11,7 @@
line-height: 22px; line-height: 22px;
background: #f4f4f4 url(docs/images/background.png); background: #f4f4f4 url(docs/images/background.png);
color: #000; color: #000;
font-family: Helvetica Neue, Helvetica, Arial; font-family: Helvetica Neue, Helvetica, Arial;
} }
.interface { .interface {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important; font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
@@ -58,7 +58,7 @@
} }
.toc_section li a:hover { .toc_section li a:hover {
text-decoration: underline; text-decoration: underline;
} }
div.container { div.container {
width: 550px; width: 550px;
margin: 40px 0 50px 260px; margin: 40px 0 50px 260px;
@@ -131,13 +131,13 @@
</style> </style>
</head> </head>
<body> <body>
<div id="sidebar" class="interface"> <div id="sidebar" class="interface">
<a class="toc_title" href="#"> <a class="toc_title" href="#">
Underscore.js <span class="version">(1.3.1)</span> Underscore.js <span class="version">(1.3.1)</span>
</a> </a>
<a class="toc_title" href="#"> <a class="toc_title" href="#">
Introduction Introduction
</a> </a>
@@ -237,7 +237,7 @@
<a class="toc_title" href="#utility"> <a class="toc_title" href="#utility">
Utility Utility
</a> </a>
<ul class="toc_section"> <ul class="toc_section">
<li>- <a href="#noConflict">noConflict</a></li> <li>- <a href="#noConflict">noConflict</a></li>
<li>- <a href="#identity">identity</a></li> <li>- <a href="#identity">identity</a></li>
@@ -245,6 +245,7 @@
<li>- <a href="#mixin">mixin</a></li> <li>- <a href="#mixin">mixin</a></li>
<li>- <a href="#uniqueId">uniqueId</a></li> <li>- <a href="#uniqueId">uniqueId</a></li>
<li>- <a href="#escape">escape</a></li> <li>- <a href="#escape">escape</a></li>
<li>- <a href="#result">result</a></li>
<li>- <a href="#template">template</a></li> <li>- <a href="#template">template</a></li>
</ul> </ul>
@@ -255,15 +256,15 @@
<li>- <a href="#chain">chain</a></li> <li>- <a href="#chain">chain</a></li>
<li>- <a href="#value">value</a></li> <li>- <a href="#value">value</a></li>
</ul> </ul>
<a class="toc_title" href="#links"> <a class="toc_title" href="#links">
Links Links
</a> </a>
<a class="toc_title" href="#changelog"> <a class="toc_title" href="#changelog">
Change Log Change Log
</a> </a>
</div> </div>
<div class="container"> <div class="container">
@@ -297,7 +298,7 @@
A complete <a href="test/test.html">Test &amp; Benchmark Suite</a> A complete <a href="test/test.html">Test &amp; Benchmark Suite</a>
is included for your perusal. is included for your perusal.
</p> </p>
<p> <p>
You may also read through the <a href="docs/underscore.html">annotated source code</a>. You may also read through the <a href="docs/underscore.html">annotated source code</a>.
</p> </p>
@@ -327,7 +328,7 @@
<td><i>&lt; 4kb, Minified and Gzipped</i></td> <td><i>&lt; 4kb, Minified and Gzipped</i></td>
</tr> </tr>
</table> </table>
<div class="warning">Upgrade warning: version 1.3.0 removes AMD (RequireJS) support.</div> <div class="warning">Upgrade warning: version 1.3.0 removes AMD (RequireJS) support.</div>
<div id="documentation"> <div id="documentation">
@@ -525,7 +526,7 @@ _.min(numbers);
<p id="sortBy"> <p id="sortBy">
<b class="header">sortBy</b><code>_.sortBy(list, iterator, [context])</code> <b class="header">sortBy</b><code>_.sortBy(list, iterator, [context])</code>
<br /> <br />
Returns a sorted copy of <b>list</b>, ranked in ascending order by the Returns a sorted copy of <b>list</b>, ranked in ascending order by the
results of running each value through <b>iterator</b>. results of running each value through <b>iterator</b>.
</p> </p>
<pre> <pre>
@@ -565,7 +566,7 @@ _.sortedIndex([10, 20, 30, 40, 50], 35);
<p id="shuffle"> <p id="shuffle">
<b class="header">shuffle</b><code>_.shuffle(list)</code> <b class="header">shuffle</b><code>_.shuffle(list)</code>
<br /> <br />
Returns a shuffled copy of the <b>list</b>, using a version of the Returns a shuffled copy of the <b>list</b>, using a version of the
<a href="http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle</a>. <a href="http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle</a>.
</p> </p>
<pre> <pre>
@@ -751,7 +752,7 @@ _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
<br /> <br />
Returns the index at which <b>value</b> can be found in the <b>array</b>, Returns the index at which <b>value</b> can be found in the <b>array</b>,
or <i>-1</i> if value is not present in the <b>array</b>. Uses the native or <i>-1</i> if value is not present in the <b>array</b>. Uses the native
<b>indexOf</b> function unless it's missing. If you're working with a <b>indexOf</b> function unless it's missing. If you're working with a
large array, and you know that the array is already sorted, pass <tt>true</tt> large array, and you know that the array is already sorted, pass <tt>true</tt>
for <b>isSorted</b> to use a faster binary search. for <b>isSorted</b> to use a faster binary search.
</p> </p>
@@ -836,7 +837,7 @@ jQuery('#underscore_button').bind('click', buttonView.onClick);
<b class="header">memoize</b><code>_.memoize(function, [hashFunction])</code> <b class="header">memoize</b><code>_.memoize(function, [hashFunction])</code>
<br /> <br />
Memoizes a given <b>function</b> by caching the computed result. Useful Memoizes a given <b>function</b> by caching the computed result. Useful
for speeding up slow-running computations. If passed an optional for speeding up slow-running computations. If passed an optional
<b>hashFunction</b>, it will be used to compute the hash key for storing <b>hashFunction</b>, it will be used to compute the hash key for storing
the result, based on the arguments to the original function. The default the result, based on the arguments to the original function. The default
<b>hashFunction</b> just uses the first argument to the memoized function <b>hashFunction</b> just uses the first argument to the memoized function
@@ -877,8 +878,8 @@ _.defer(function(){ alert('deferred'); });
<p id="throttle"> <p id="throttle">
<b class="header">throttle</b><code>_.throttle(function, wait)</code> <b class="header">throttle</b><code>_.throttle(function, wait)</code>
<br /> <br />
Creates and returns a new, throttled version of the passed function, Creates and returns a new, throttled version of the passed function,
that, when invoked repeatedly, will only actually call the original function that, when invoked repeatedly, will only actually call the original function
at most once per every <b>wait</b> at most once per every <b>wait</b>
milliseconds. Useful for rate-limiting events that occur faster than you milliseconds. Useful for rate-limiting events that occur faster than you
can keep up with. can keep up with.
@@ -892,11 +893,11 @@ $(window).scroll(throttled);
<b class="header">debounce</b><code>_.debounce(function, wait)</code> <b class="header">debounce</b><code>_.debounce(function, wait)</code>
<br /> <br />
Creates and returns a new debounced version of the passed function that Creates and returns a new debounced version of the passed function that
will postpone its execution until after will postpone its execution until after
<b>wait</b> milliseconds have elapsed since the last time it <b>wait</b> milliseconds have elapsed since the last time it
was invoked. Useful for implementing behavior that should only happen was invoked. Useful for implementing behavior that should only happen
<i>after</i> the input has stopped arriving. For example: rendering a <i>after</i> the input has stopped arriving. For example: rendering a
preview of a Markdown comment, recalculating a layout after the window preview of a Markdown comment, recalculating a layout after the window
has stopped being resized, and so on. has stopped being resized, and so on.
</p> </p>
<pre> <pre>
@@ -907,7 +908,7 @@ $(window).resize(lazyLayout);
<p id="once"> <p id="once">
<b class="header">once</b><code>_.once(function)</code> <b class="header">once</b><code>_.once(function)</code>
<br /> <br />
Creates a version of the function that can only be called one time. Creates a version of the function that can only be called one time.
Repeated calls to the modified function will have no effect, returning Repeated calls to the modified function will have no effect, returning
the value from the original call. Useful for initialization functions, the value from the original call. Useful for initialization functions,
instead of having to set a boolean flag and then check it later. instead of having to set a boolean flag and then check it later.
@@ -922,7 +923,7 @@ initialize();
<p id="after"> <p id="after">
<b class="header">after</b><code>_.after(count, function)</code> <b class="header">after</b><code>_.after(count, function)</code>
<br /> <br />
Creates a version of the function that will only be run after first Creates a version of the function that will only be run after first
being called <b>count</b> times. Useful for grouping asynchronous responses, being called <b>count</b> times. Useful for grouping asynchronous responses,
where you want to be sure that all the async calls have finished, before where you want to be sure that all the async calls have finished, before
proceeding. proceeding.
@@ -930,7 +931,7 @@ initialize();
<pre> <pre>
var renderNotes = _.after(notes.length, render); var renderNotes = _.after(notes.length, render);
_.each(notes, function(note) { _.each(notes, function(note) {
note.asyncSave({success: renderNotes}); note.asyncSave({success: renderNotes});
}); });
// renderNotes is run once, after all notes have saved. // renderNotes is run once, after all notes have saved.
</pre> </pre>
@@ -1058,9 +1059,9 @@ _.chain([1,2,3,200])
<p id="has"> <p id="has">
<b class="header">has</b><code>_.has(object, key)</code> <b class="header">has</b><code>_.has(object, key)</code>
<br /> <br />
Does the object contain the given key? Identical to Does the object contain the given key? Identical to
<tt>object.hasOwnProperty(key)</tt>, but uses a safe reference to the <tt>object.hasOwnProperty(key)</tt>, but uses a safe reference to the
<tt>hasOwnProperty</tt> function, in case it's been <tt>hasOwnProperty</tt> function, in case it's been
<a href="http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/">overridden accidentally</a>. <a href="http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/">overridden accidentally</a>.
</p> </p>
<pre> <pre>
@@ -1238,7 +1239,7 @@ _.isNull(undefined);
_.isUndefined(window.missingVariable); _.isUndefined(window.missingVariable);
=&gt; true =&gt; true
</pre> </pre>
<h2 id="utility">Utility Functions</h2> <h2 id="utility">Utility Functions</h2>
<p id="noConflict"> <p id="noConflict">
@@ -1275,7 +1276,7 @@ _(3).times(function(){ genie.grantWish(); });</pre>
<b class="header">mixin</b><code>_.mixin(object)</code> <b class="header">mixin</b><code>_.mixin(object)</code>
<br /> <br />
Allows you to extend Underscore with your own utility functions. Pass Allows you to extend Underscore with your own utility functions. Pass
a hash of <tt>{name: function}</tt> definitions to have your functions a hash of <tt>{name: function}</tt> definitions to have your functions
added to the Underscore object, as well as the OOP wrapper. added to the Underscore object, as well as the OOP wrapper.
</p> </p>
<pre> <pre>
@@ -1302,19 +1303,31 @@ _.uniqueId('contact_');
<p id="escape"> <p id="escape">
<b class="header">escape</b><code>_.escape(string)</code> <b class="header">escape</b><code>_.escape(string)</code>
<br /> <br />
Escapes a string for insertion into HTML, replacing Escapes a string for insertion into HTML, replacing
<tt>&amp;</tt>, <tt>&lt;</tt>, <tt>&gt;</tt>, <tt>&quot;</tt>, <tt>&#x27;</tt>, and <tt>&#x2F;</tt> characters. <tt>&amp;</tt>, <tt>&lt;</tt>, <tt>&gt;</tt>, <tt>&quot;</tt>, <tt>&#x27;</tt>, and <tt>&#x2F;</tt> characters.
</p> </p>
<pre> <pre>
_.escape('Curly, Larry &amp; Moe'); _.escape('Curly, Larry &amp; Moe');
=&gt; "Curly, Larry &amp;amp; Moe"</pre> =&gt; "Curly, Larry &amp;amp; Moe"</pre>
<p id="result">
<b class="header">result</b><code>_.result(object, property)</code>
<br />
If the value of the named property is a function then invoke it; otherwise, return it.
</p>
<pre>
var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
_.result(object, 'cheese');
=&gt; "crumpets"
_.result(object, 'stuff');
=&gt; "nonsense"</pre>
<p id="template"> <p id="template">
<b class="header">template</b><code>_.template(templateString, [context])</code> <b class="header">template</b><code>_.template(templateString, [context])</code>
<br /> <br />
Compiles JavaScript templates into functions that can be evaluated Compiles JavaScript templates into functions that can be evaluated
for rendering. Useful for rendering complicated bits of HTML from JSON for rendering. Useful for rendering complicated bits of HTML from JSON
data sources. Template functions can both interpolate variables, using<br /> data sources. Template functions can both interpolate variables, using
<tt>&lt;%= &hellip; %&gt;</tt>, as well as execute arbitrary JavaScript code, with <tt>&lt;%= &hellip; %&gt;</tt>, as well as execute arbitrary JavaScript code, with
<tt>&lt;% &hellip; %&gt;</tt>. If you wish to interpolate a value, and have <tt>&lt;% &hellip; %&gt;</tt>. If you wish to interpolate a value, and have
it be HTML-escaped, use <tt>&lt;%- &hellip; %&gt;</tt> When you evaluate a template function, pass in a it be HTML-escaped, use <tt>&lt;%- &hellip; %&gt;</tt> When you evaluate a template function, pass in a
@@ -1340,7 +1353,7 @@ template({value : '&lt;script&gt;'});
You can also use <tt>print</tt> from within JavaScript code. This is You can also use <tt>print</tt> from within JavaScript code. This is
sometimes more convenient than using <tt>&lt;%= ... %&gt;</tt>. sometimes more convenient than using <tt>&lt;%= ... %&gt;</tt>.
</p> </p>
<pre> <pre>
var compiled = _.template("&lt;% print('Hello ' + epithet); %&gt;"); var compiled = _.template("&lt;% print('Hello ' + epithet); %&gt;");
compiled({epithet: "stooge"}); compiled({epithet: "stooge"});
@@ -1349,8 +1362,8 @@ compiled({epithet: "stooge"});
<p> <p>
If ERB-style delimiters aren't your cup of tea, you can change Underscore's If ERB-style delimiters aren't your cup of tea, you can change Underscore's
template settings to use different symbols to set off interpolated code. template settings to use different symbols to set off interpolated code.
Define an <b>interpolate</b> regex to match expressions that should be Define an <b>interpolate</b> regex to match expressions that should be
interpolated verbatim, an <b>escape</b> regex to match expressions that should interpolated verbatim, an <b>escape</b> regex to match expressions that should
be inserted after being HTML escaped, and an <b>evaluate</b> regex to match be inserted after being HTML escaped, and an <b>evaluate</b> regex to match
expressions that should be evaluated without insertion into the resulting expressions that should be evaluated without insertion into the resulting
string. You may define or omit any combination of the three. string. You may define or omit any combination of the three.
@@ -1368,6 +1381,18 @@ var template = _.template("Hello {{ name }}!");
template({name : "Mustache"}); template({name : "Mustache"});
=&gt; "Hello Mustache!"</pre> =&gt; "Hello Mustache!"</pre>
<p>
Precompiling your templates can be a big help when debugging errors you can't
reproduce. This is because precompiled templates can provide line numbers and
a stack trace, something that is not possible when compiling templates on the client.
<b>template</b> provides the <b>source</b> property on the compiled template
function for easy precompilation.
</p>
<pre>&lt;script&gt;
JST.project = <%= _.template(jstText).source %>;
&lt;/script&gt;</pre>
<h2 id="chaining">Chaining</h2> <h2 id="chaining">Chaining</h2>
@@ -1450,7 +1475,7 @@ _([1, 2, 3]).value();
The <a href="http://github.com/mirven/underscore.lua">source</a> is The <a href="http://github.com/mirven/underscore.lua">source</a> is
available on GitHub. available on GitHub.
</p> </p>
<p> <p>
<a href="http://brianhaveri.github.com/Underscore.php/">Underscore.php</a>, <a href="http://brianhaveri.github.com/Underscore.php/">Underscore.php</a>,
a PHP port of the functions that are applicable in both languages. a PHP port of the functions that are applicable in both languages.
@@ -1458,17 +1483,17 @@ _([1, 2, 3]).value();
The <a href="http://github.com/brianhaveri/Underscore.php">source</a> is The <a href="http://github.com/brianhaveri/Underscore.php">source</a> is
available on GitHub. available on GitHub.
</p> </p>
<p> <p>
<a href="http://vti.github.com/underscore-perl/">Underscore-perl</a>, <a href="http://vti.github.com/underscore-perl/">Underscore-perl</a>,
a Perl port of many of the Underscore.js functions, a Perl port of many of the Underscore.js functions,
aimed at on Perl hashes and arrays, also aimed at on Perl hashes and arrays, also
<a href="https://github.com/vti/underscore-perl/">available on GitHub</a>. <a href="https://github.com/vti/underscore-perl/">available on GitHub</a>.
</p> </p>
<p> <p>
<a href="https://github.com/edtsech/underscore.string">Underscore.string</a>, <a href="https://github.com/edtsech/underscore.string">Underscore.string</a>,
an Underscore extension that adds functions for string-manipulation: an Underscore extension that adds functions for string-manipulation:
<tt>trim</tt>, <tt>startsWith</tt>, <tt>contains</tt>, <tt>capitalize</tt>, <tt>trim</tt>, <tt>startsWith</tt>, <tt>contains</tt>, <tt>capitalize</tt>,
<tt>reverse</tt>, <tt>sprintf</tt>, and more. <tt>reverse</tt>, <tt>sprintf</tt>, and more.
</p> </p>
@@ -1487,7 +1512,7 @@ _([1, 2, 3]).value();
<a href="http://osteele.com/sources/javascript/functional/">Functional JavaScript</a>, <a href="http://osteele.com/sources/javascript/functional/">Functional JavaScript</a>,
which includes comprehensive higher-order function support as well as string lambdas. which includes comprehensive higher-order function support as well as string lambdas.
</p> </p>
<p> <p>
Michael Aufreiter's <a href="http://substance.io/#michael/data-js">Data.js</a>, Michael Aufreiter's <a href="http://substance.io/#michael/data-js">Data.js</a>,
a data manipulation + persistence library for JavaScript. a data manipulation + persistence library for JavaScript.
@@ -1498,7 +1523,7 @@ _([1, 2, 3]).value();
</p> </p>
<h2 id="changelog">Change Log</h2> <h2 id="changelog">Change Log</h2>
<p> <p>
<b class="header">1.3.1</b> &mdash; <small><i>Jan. 23, 2012</i></small><br /> <b class="header">1.3.1</b> &mdash; <small><i>Jan. 23, 2012</i></small><br />
<ul> <ul>
@@ -1509,7 +1534,7 @@ _([1, 2, 3]).value();
Added <tt>_.collect</tt> as an alias for <tt>_.map</tt>. Smalltalkers, rejoice. Added <tt>_.collect</tt> as an alias for <tt>_.map</tt>. Smalltalkers, rejoice.
</li> </li>
<li> <li>
Reverted an old change so that <tt>_.extend</tt> will correctly copy Reverted an old change so that <tt>_.extend</tt> will correctly copy
over keys with undefined values again. over keys with undefined values again.
</li> </li>
<li> <li>
@@ -1517,7 +1542,7 @@ _([1, 2, 3]).value();
</li> </li>
</ul> </ul>
</p> </p>
<p> <p>
<b class="header">1.3.0</b> &mdash; <small><i>Jan. 11, 2012</i></small><br /> <b class="header">1.3.0</b> &mdash; <small><i>Jan. 11, 2012</i></small><br />
<ul> <ul>
@@ -1528,7 +1553,7 @@ _([1, 2, 3]).value();
</li> </li>
</ul> </ul>
</p> </p>
<p> <p>
<b class="header">1.2.4</b> &mdash; <small><i>Jan. 4, 2012</i></small><br /> <b class="header">1.2.4</b> &mdash; <small><i>Jan. 4, 2012</i></small><br />
<ul> <ul>
@@ -1551,7 +1576,7 @@ _([1, 2, 3]).value();
</li> </li>
</ul> </ul>
</p> </p>
<p> <p>
<b class="header">1.2.3</b> &mdash; <small><i>Dec. 7, 2011</i></small><br /> <b class="header">1.2.3</b> &mdash; <small><i>Dec. 7, 2011</i></small><br />
<ul> <ul>
@@ -1564,12 +1589,12 @@ _([1, 2, 3]).value();
</li> </li>
<li> <li>
Both <tt>_.reduce</tt> and <tt>_.reduceRight</tt> can now be passed an Both <tt>_.reduce</tt> and <tt>_.reduceRight</tt> can now be passed an
explicitly <tt>undefined</tt> value. (There's no reason why you'd explicitly <tt>undefined</tt> value. (There's no reason why you'd
want to do this.) want to do this.)
</li> </li>
</ul> </ul>
</p> </p>
<p> <p>
<b class="header">1.2.2</b> &mdash; <small><i>Nov. 14, 2011</i></small><br /> <b class="header">1.2.2</b> &mdash; <small><i>Nov. 14, 2011</i></small><br />
<ul> <ul>
@@ -1588,22 +1613,22 @@ _([1, 2, 3]).value();
</li> </li>
<li> <li>
<tt>_.after(callback, 0)</tt> will now trigger the callback immediately, <tt>_.after(callback, 0)</tt> will now trigger the callback immediately,
making "after" easier to use with asynchronous APIs <small>(#366)</small>. making "after" easier to use with asynchronous APIs <small>(#366)</small>.
</li> </li>
</ul> </ul>
</p> </p>
<p> <p>
<b class="header">1.2.1</b> &mdash; <small><i>Oct. 24, 2011</i></small><br /> <b class="header">1.2.1</b> &mdash; <small><i>Oct. 24, 2011</i></small><br />
<ul> <ul>
<li> <li>
Several important bug fixes for <tt>_.isEqual</tt>, which should now Several important bug fixes for <tt>_.isEqual</tt>, which should now
do better on mutated Arrays, and on non-Array objects with do better on mutated Arrays, and on non-Array objects with
<tt>length</tt> properties. <small>(#329)</small> <tt>length</tt> properties. <small>(#329)</small>
</li> </li>
<li> <li>
<b>jrburke</b> contributed Underscore exporting for AMD module loaders, <b>jrburke</b> contributed Underscore exporting for AMD module loaders,
and <b>tonylukasavage</b> for Appcelerator Titanium. and <b>tonylukasavage</b> for Appcelerator Titanium.
<small>(#335, #338)</small> <small>(#335, #338)</small>
</li> </li>
<li> <li>
@@ -1611,7 +1636,7 @@ _([1, 2, 3]).value();
grouping values by a particular common property. grouping values by a particular common property.
</li> </li>
<li> <li>
<tt>_.throttle</tt>'d functions now fire immediately upon invocation, <tt>_.throttle</tt>'d functions now fire immediately upon invocation,
and are rate-limited thereafter <small>(#170, #266)</small>. and are rate-limited thereafter <small>(#170, #266)</small>.
</li> </li>
<li> <li>
@@ -1619,7 +1644,7 @@ _([1, 2, 3]).value();
</li> </li>
<li> <li>
The <tt>_.bind</tt> function now also works on constructors, a-la The <tt>_.bind</tt> function now also works on constructors, a-la
ES5 ... but you would never want to use <tt>_.bind</tt> on a ES5 ... but you would never want to use <tt>_.bind</tt> on a
constructor function. constructor function.
</li> </li>
<li> <li>
@@ -1631,25 +1656,25 @@ _([1, 2, 3]).value();
</li> </li>
</ul> </ul>
</p> </p>
<p> <p>
<b class="header">1.2.0</b> &mdash; <small><i>Oct. 5, 2011</i></small><br /> <b class="header">1.2.0</b> &mdash; <small><i>Oct. 5, 2011</i></small><br />
<ul> <ul>
<li> <li>
The <tt>_.isEqual</tt> function now The <tt>_.isEqual</tt> function now
supports true deep equality comparisons, with checks for cyclic structures, supports true deep equality comparisons, with checks for cyclic structures,
thanks to Kit Cambridge. thanks to Kit Cambridge.
</li> </li>
<li> <li>
Underscore templates now support HTML escaping interpolations, using Underscore templates now support HTML escaping interpolations, using
<tt>&lt;%- ... %&gt;</tt> syntax. <tt>&lt;%- ... %&gt;</tt> syntax.
</li> </li>
<li> <li>
Ryan Tenney contributed <tt>_.shuffle</tt>, which uses a modified Ryan Tenney contributed <tt>_.shuffle</tt>, which uses a modified
Fisher-Yates to give you a shuffled copy of an array. Fisher-Yates to give you a shuffled copy of an array.
</li> </li>
<li> <li>
<tt>_.uniq</tt> can now be passed an optional iterator, to determine by <tt>_.uniq</tt> can now be passed an optional iterator, to determine by
what criteria an object should be considered unique. what criteria an object should be considered unique.
</li> </li>
<li> <li>
@@ -1658,22 +1683,22 @@ _([1, 2, 3]).value();
</li> </li>
<li> <li>
A new <tt>_.initial</tt> function was added, as a mirror of <tt>_.rest</tt>, A new <tt>_.initial</tt> function was added, as a mirror of <tt>_.rest</tt>,
which returns all the initial values of a list (except the last N). which returns all the initial values of a list (except the last N).
</li> </li>
</ul> </ul>
</p> </p>
<p> <p>
<b class="header">1.1.7</b> &mdash; <small><i>July 13, 2011</i></small><br /> <b class="header">1.1.7</b> &mdash; <small><i>July 13, 2011</i></small><br />
Added <tt>_.groupBy</tt>, which aggregates a collection into groups of like items. Added <tt>_.groupBy</tt>, which aggregates a collection into groups of like items.
Added <tt>_.union</tt> and <tt>_.difference</tt>, to complement the Added <tt>_.union</tt> and <tt>_.difference</tt>, to complement the
(re-named) <tt>_.intersection</tt>. (re-named) <tt>_.intersection</tt>.
Various improvements for support of sparse arrays. Various improvements for support of sparse arrays.
<tt>_.toArray</tt> now returns a clone, if directly passed an array. <tt>_.toArray</tt> now returns a clone, if directly passed an array.
<tt>_.functions</tt> now also returns the names of functions that are present <tt>_.functions</tt> now also returns the names of functions that are present
in the prototype chain. in the prototype chain.
</p> </p>
<p> <p>
<b class="header">1.1.6</b> &mdash; <small><i>April 18, 2011</i></small><br /> <b class="header">1.1.6</b> &mdash; <small><i>April 18, 2011</i></small><br />
Added <tt>_.after</tt>, which will return a function that only runs after Added <tt>_.after</tt>, which will return a function that only runs after
@@ -1684,30 +1709,30 @@ _([1, 2, 3]).value();
<tt>_.extend</tt> no longer copies keys when the value is undefined. <tt>_.extend</tt> no longer copies keys when the value is undefined.
<tt>_.bind</tt> now errors when trying to bind an undefined value. <tt>_.bind</tt> now errors when trying to bind an undefined value.
</p> </p>
<p> <p>
<b class="header">1.1.5</b> &mdash; <small><i>Mar 20, 2011</i></small><br /> <b class="header">1.1.5</b> &mdash; <small><i>Mar 20, 2011</i></small><br />
Added an <tt>_.defaults</tt> function, for use merging together JS objects Added an <tt>_.defaults</tt> function, for use merging together JS objects
representing default options. representing default options.
Added an <tt>_.once</tt> function, for manufacturing functions that should Added an <tt>_.once</tt> function, for manufacturing functions that should
only ever execute a single time. only ever execute a single time.
<tt>_.bind</tt> now delegates to the native ECMAScript 5 version, <tt>_.bind</tt> now delegates to the native ECMAScript 5 version,
where available. where available.
<tt>_.keys</tt> now throws an error when used on non-Object values, as in <tt>_.keys</tt> now throws an error when used on non-Object values, as in
ECMAScript 5. ECMAScript 5.
Fixed a bug with <tt>_.keys</tt> when used over sparse arrays. Fixed a bug with <tt>_.keys</tt> when used over sparse arrays.
</p> </p>
<p> <p>
<b class="header">1.1.4</b> &mdash; <small><i>Jan 9, 2011</i></small><br /> <b class="header">1.1.4</b> &mdash; <small><i>Jan 9, 2011</i></small><br />
Improved compliance with ES5's Array methods when passing <tt>null</tt> Improved compliance with ES5's Array methods when passing <tt>null</tt>
as a value. <tt>_.wrap</tt> now correctly sets <tt>this</tt> for the as a value. <tt>_.wrap</tt> now correctly sets <tt>this</tt> for the
wrapped function. <tt>_.indexOf</tt> now takes an optional flag for wrapped function. <tt>_.indexOf</tt> now takes an optional flag for
finding the insertion index in an array that is guaranteed to already finding the insertion index in an array that is guaranteed to already
be sorted. Avoiding the use of <tt>.callee</tt>, to allow <tt>_.isArray</tt> be sorted. Avoiding the use of <tt>.callee</tt>, to allow <tt>_.isArray</tt>
to work properly in ES5's strict mode. to work properly in ES5's strict mode.
</p> </p>
<p> <p>
<b class="header">1.1.3</b> &mdash; <small><i>Dec 1, 2010</i></small><br /> <b class="header">1.1.3</b> &mdash; <small><i>Dec 1, 2010</i></small><br />
In CommonJS, Underscore may now be required with just: <br /> In CommonJS, Underscore may now be required with just: <br />
@@ -1719,26 +1744,26 @@ _([1, 2, 3]).value();
Improved the <b>isType</b> family of functions for better interoperability Improved the <b>isType</b> family of functions for better interoperability
with Internet Explorer host objects. with Internet Explorer host objects.
<tt>_.template</tt> now correctly escapes backslashes in templates. <tt>_.template</tt> now correctly escapes backslashes in templates.
Improved <tt>_.reduce</tt> compatibility with the ECMA5 version: Improved <tt>_.reduce</tt> compatibility with the ECMA5 version:
if you don't pass an initial value, the first item in the collection is used. if you don't pass an initial value, the first item in the collection is used.
<tt>_.each</tt> no longer returns the iterated collection, for improved <tt>_.each</tt> no longer returns the iterated collection, for improved
consistency with ES5's <tt>forEach</tt>. consistency with ES5's <tt>forEach</tt>.
</p> </p>
<p> <p>
<b class="header">1.1.2</b><br /> <b class="header">1.1.2</b><br />
Fixed <tt>_.contains</tt>, which was mistakenly pointing at Fixed <tt>_.contains</tt>, which was mistakenly pointing at
<tt>_.intersect</tt> instead of <tt>_.include</tt>, like it should <tt>_.intersect</tt> instead of <tt>_.include</tt>, like it should
have been. Added <tt>_.unique</tt> as an alias for <tt>_.uniq</tt>. have been. Added <tt>_.unique</tt> as an alias for <tt>_.uniq</tt>.
</p> </p>
<p> <p>
<b class="header">1.1.1</b><br /> <b class="header">1.1.1</b><br />
Improved the speed of <tt>_.template</tt>, and its handling of multiline Improved the speed of <tt>_.template</tt>, and its handling of multiline
interpolations. Ryan Tenney contributed optimizations to many Underscore interpolations. Ryan Tenney contributed optimizations to many Underscore
functions. An annotated version of the source code is now available. functions. An annotated version of the source code is now available.
</p> </p>
<p> <p>
<b class="header">1.1.0</b><br /> <b class="header">1.1.0</b><br />
The method signature of <tt>_.reduce</tt> has been changed to match The method signature of <tt>_.reduce</tt> has been changed to match
@@ -1747,33 +1772,33 @@ _([1, 2, 3]).value();
called with no arguments, and preserves whitespace. <tt>_.contains</tt> called with no arguments, and preserves whitespace. <tt>_.contains</tt>
is a new alias for <tt>_.include</tt>. is a new alias for <tt>_.include</tt>.
</p> </p>
<p> <p>
<b class="header">1.0.4</b><br /> <b class="header">1.0.4</b><br />
<a href="http://themoell.com/">Andri Möll</a> contributed the <tt>_.memoize</tt> <a href="http://themoell.com/">Andri Möll</a> contributed the <tt>_.memoize</tt>
function, which can be used to speed up expensive repeated computations function, which can be used to speed up expensive repeated computations
by caching the results. by caching the results.
</p> </p>
<p> <p>
<b class="header">1.0.3</b><br /> <b class="header">1.0.3</b><br />
Patch that makes <tt>_.isEqual</tt> return <tt>false</tt> if any property Patch that makes <tt>_.isEqual</tt> return <tt>false</tt> if any property
of the compared object has a <tt>NaN</tt> value. Technically the correct of the compared object has a <tt>NaN</tt> value. Technically the correct
thing to do, but of questionable semantics. Watch out for NaN comparisons. thing to do, but of questionable semantics. Watch out for NaN comparisons.
</p> </p>
<p> <p>
<b class="header">1.0.2</b><br /> <b class="header">1.0.2</b><br />
Fixes <tt>_.isArguments</tt> in recent versions of Opera, which have Fixes <tt>_.isArguments</tt> in recent versions of Opera, which have
arguments objects as real Arrays. arguments objects as real Arrays.
</p> </p>
<p> <p>
<b class="header">1.0.1</b><br /> <b class="header">1.0.1</b><br />
Bugfix for <tt>_.isEqual</tt>, when comparing two objects with the same Bugfix for <tt>_.isEqual</tt>, when comparing two objects with the same
number of undefined keys, but with different names. number of undefined keys, but with different names.
</p> </p>
<p> <p>
<b class="header">1.0.0</b><br /> <b class="header">1.0.0</b><br />
Things have been stable for many months now, so Underscore is now Things have been stable for many months now, so Underscore is now
@@ -1781,15 +1806,15 @@ _([1, 2, 3]).value();
include <tt>_.isBoolean</tt>, and the ability to have <tt>_.extend</tt> include <tt>_.isBoolean</tt>, and the ability to have <tt>_.extend</tt>
take multiple source objects. take multiple source objects.
</p> </p>
<p> <p>
<b class="header">0.6.0</b><br /> <b class="header">0.6.0</b><br />
Major release. Incorporates a number of Major release. Incorporates a number of
<a href="http://github.com/ratbeard">Mile Frawley's</a> refactors for <a href="http://github.com/ratbeard">Mile Frawley's</a> refactors for
safer duck-typing on collection functions, and cleaner internals. A new safer duck-typing on collection functions, and cleaner internals. A new
<tt>_.mixin</tt> method that allows you to extend Underscore with utility <tt>_.mixin</tt> method that allows you to extend Underscore with utility
functions of your own. Added <tt>_.times</tt>, which works the same as in functions of your own. Added <tt>_.times</tt>, which works the same as in
Ruby or Prototype.js. Native support for ECMAScript 5's <tt>Array.isArray</tt>, Ruby or Prototype.js. Native support for ECMAScript 5's <tt>Array.isArray</tt>,
and <tt>Object.keys</tt>. and <tt>Object.keys</tt>.
</p> </p>
@@ -1847,7 +1872,7 @@ _([1, 2, 3]).value();
<b class="header">0.5.1</b><br /> <b class="header">0.5.1</b><br />
Added an <tt>_.isArguments</tt> function. Lots of little safety checks Added an <tt>_.isArguments</tt> function. Lots of little safety checks
and optimizations contributed by and optimizations contributed by
<a href="http://github.com/iamnoah/">Noah Sloan</a> and <a href="http://github.com/iamnoah/">Noah Sloan</a> and
<a href="http://themoell.com/">Andri Möll</a>. <a href="http://themoell.com/">Andri Möll</a>.
</p> </p>

View File

@@ -275,6 +275,7 @@ $(document).ready(function() {
test('collections: size', function() { test('collections: size', function() {
equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object'); equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object');
equal(_.size([1, 2, 3]), 3, 'can compute the size of an array');
}); });
}); });

View File

@@ -101,8 +101,8 @@ $(document).ready(function() {
setTimeout(throttledIncr, 190); setTimeout(throttledIncr, 190);
setTimeout(throttledIncr, 220); setTimeout(throttledIncr, 220);
setTimeout(throttledIncr, 240); setTimeout(throttledIncr, 240);
_.delay(function(){ ok(counter == 1, "incr was called immediately"); }, 30); _.delay(function(){ equal(counter, 1, "incr was called immediately"); }, 30);
_.delay(function(){ ok(counter == 4, "incr was throttled"); start(); }, 400); _.delay(function(){ equal(counter, 4, "incr was throttled"); start(); }, 400);
}); });
asyncTest("functions: throttle arguments", 2, function() { asyncTest("functions: throttle arguments", 2, function() {
@@ -122,7 +122,7 @@ $(document).ready(function() {
var incr = function(){ counter++; }; var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100); var throttledIncr = _.throttle(incr, 100);
throttledIncr(); throttledIncr();
_.delay(function(){ ok(counter == 1, "incr was called once"); start(); }, 220); _.delay(function(){ equal(counter, 1, "incr was called once"); start(); }, 220);
}); });
asyncTest("functions: throttle twice", 1, function() { asyncTest("functions: throttle twice", 1, function() {
@@ -130,7 +130,7 @@ $(document).ready(function() {
var incr = function(){ counter++; }; var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100); var throttledIncr = _.throttle(incr, 100);
throttledIncr(); throttledIncr(); throttledIncr(); throttledIncr();
_.delay(function(){ ok(counter == 2, "incr was called twice"); start(); }, 220); _.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 220);
}); });
asyncTest("functions: debounce", 1, function() { asyncTest("functions: debounce", 1, function() {
@@ -143,7 +143,7 @@ $(document).ready(function() {
setTimeout(debouncedIncr, 90); setTimeout(debouncedIncr, 90);
setTimeout(debouncedIncr, 120); setTimeout(debouncedIncr, 120);
setTimeout(debouncedIncr, 150); setTimeout(debouncedIncr, 150);
_.delay(function(){ ok(counter == 1, "incr was debounced"); start(); }, 220); _.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220);
}); });
asyncTest("functions: debounce asap", 2, function() { asyncTest("functions: debounce asap", 2, function() {

View File

@@ -18,6 +18,7 @@
<body> <body>
<div class="underscore-test"> <div class="underscore-test">
<h1 id="qunit-header">Underscore Test Suite</h1> <h1 id="qunit-header">Underscore Test Suite</h1>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-banner"></h2> <h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2> <h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol> <ol id="qunit-tests"></ol>
@@ -34,6 +35,7 @@
<script type="text/html" id="template"> <script type="text/html" id="template">
<% <%
// a comment
if (data) { data += 12345; }; %> if (data) { data += 12345; }; %>
<li><%= data %></li> <li><%= data %></li>
</script> </script>

View File

@@ -1,6 +1,14 @@
$(document).ready(function() { $(document).ready(function() {
module("Utility"); var templateSettings = _.templateSettings;
module("Utility", {
teardown: function() {
_.templateSettings = templateSettings;
}
});
test("utility: noConflict", function() { test("utility: noConflict", function() {
var underscore = _.noConflict(); var underscore = _.noConflict();
@@ -152,4 +160,18 @@ $(document).ready(function() {
equal(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings"); equal(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings");
}); });
test('_.template handles \\u2028 & \\u2029', function() {
var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>');
strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
});
test('result calls functions and returns primitives', function() {
var obj = {w: '', x: 'x', y: function(){ return this.x; }};
strictEqual(_.result(obj, 'w'), '');
strictEqual(_.result(obj, 'x'), 'x');
strictEqual(_.result(obj, 'y'), 'x');
strictEqual(_.result(obj, 'z'), undefined);
strictEqual(_.result(null, 'x'), null);
});
}); });

View File

@@ -309,7 +309,7 @@
// Return the number of elements in an object. // Return the number of elements in an object.
_.size = function(obj) { _.size = function(obj) {
return _.toArray(obj).length; return _.isArray(obj) ? obj.length : _.keys(obj).length;
}; };
// Array Functions // Array Functions
@@ -873,6 +873,14 @@
return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;'); return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
}; };
// If the value of the named property is a function then invoke it;
// otherwise, return it.
_.result = function(object, property) {
if (object == null) return null;
var value = object[property];
return _.isFunction(value) ? value.call(object) : value;
};
// Add your own custom functions to the Underscore object, ensuring that // Add your own custom functions to the Underscore object, ensuring that
// they're correctly added to the OOP wrapper as well. // they're correctly added to the OOP wrapper as well.
_.mixin = function(obj) { _.mixin = function(obj) {
@@ -902,39 +910,58 @@
// guaranteed not to match. // guaranteed not to match.
var noMatch = /.^/; var noMatch = /.^/;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var escapes = {
'\\': '\\',
"'": "'",
'r': '\r',
'n': '\n',
't': '\t',
'u2028': '\u2028',
'u2029': '\u2029'
};
for (var p in escapes) escapes[escapes[p]] = p;
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
// Within an interpolation, evaluation, or escaping, remove HTML escaping // Within an interpolation, evaluation, or escaping, remove HTML escaping
// that had been previously added. // that had been previously added.
var unescape = function(code) { var unescape = function(code) {
return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'"); return code.replace(unescaper, function(match, escape) {
return escapes[escape];
});
}; };
// JavaScript micro-templating, similar to John Resig's implementation. // JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
_.template = function(str, data) { _.template = function(str, data) {
var c = _.templateSettings; var settings = _.templateSettings;
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + var source = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
'with(obj||{}){__p.push(\'' + 'with(obj||{}){__p.push(\'' +
str.replace(/\\/g, '\\\\') str
.replace(/'/g, "\\'") .replace(escaper, function(match) {
.replace(c.escape || noMatch, function(match, code) { return '\\' + escapes[match];
return "',_.escape(" + unescape(code) + "),'"; })
}) .replace(settings.escape || noMatch, function(match, code) {
.replace(c.interpolate || noMatch, function(match, code) { return "',\n_.escape(" + unescape(code) + "),\n'";
return "'," + unescape(code) + ",'"; })
}) .replace(settings.interpolate || noMatch, function(match, code) {
.replace(c.evaluate || noMatch, function(match, code) { return "',\n" + unescape(code) + ",\n'";
return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('"; })
}) .replace(settings.evaluate || noMatch, function(match, code) {
.replace(/\r/g, '\\r') return "');\n" + unescape(code) + "\n;__p.push('";
.replace(/\n/g, '\\n') })
.replace(/\t/g, '\\t') + "');\n}\nreturn __p.join('');";
+ "');}return __p.join('');"; var render = new Function('obj', '_', source);
var func = new Function('obj', '_', tmpl); if (data) return render(data, _);
if (data) return func(data, _); var template = function(data) {
return function(data) { return render.call(this, data, _);
return func.call(this, data, _);
}; };
template.source = 'function(obj){\n' + source + '\n}';
return template;
}; };
// Add a "chain" function, which will delegate to the wrapper. // Add a "chain" function, which will delegate to the wrapper.