mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-08 10:17:48 +00:00
resolving merge
This commit is contained in:
27
index.html
27
index.html
@@ -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>
|
||||||
|
|
||||||
@@ -1309,12 +1310,24 @@ _.uniqueId('contact_');
|
|||||||
_.escape('Curly, Larry & Moe');
|
_.escape('Curly, Larry & Moe');
|
||||||
=> "Curly, Larry &amp; Moe"</pre>
|
=> "Curly, Larry &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');
|
||||||
|
=> "crumpets"
|
||||||
|
_.result(object, 'stuff');
|
||||||
|
=> "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><%= … %></tt>, as well as execute arbitrary JavaScript code, with
|
<tt><%= … %></tt>, as well as execute arbitrary JavaScript code, with
|
||||||
<tt><% … %></tt>. If you wish to interpolate a value, and have
|
<tt><% … %></tt>. If you wish to interpolate a value, and have
|
||||||
it be HTML-escaped, use <tt><%- … %></tt> When you evaluate a template function, pass in a
|
it be HTML-escaped, use <tt><%- … %></tt> When you evaluate a template function, pass in a
|
||||||
@@ -1368,6 +1381,18 @@ var template = _.template("Hello {{ name }}!");
|
|||||||
template({name : "Mustache"});
|
template({name : "Mustache"});
|
||||||
=> "Hello Mustache!"</pre>
|
=> "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><script>
|
||||||
|
JST.project = <%= _.template(jstText).source %>;
|
||||||
|
</script></pre>
|
||||||
|
|
||||||
|
|
||||||
<h2 id="chaining">Chaining</h2>
|
<h2 id="chaining">Chaining</h2>
|
||||||
|
|
||||||
|
|||||||
@@ -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');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
|
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|||||||
Reference in New Issue
Block a user