Update vendors.

Former-commit-id: ad3284b1e77cfb0b17af99e0ddaf00618e4485b7
This commit is contained in:
John-David Dalton
2012-09-04 21:20:22 -07:00
parent ba948a38e9
commit 22d3794d22
13 changed files with 842 additions and 230 deletions

View File

@@ -18,8 +18,10 @@
// restored later on, if `noConflict` is used.
var previousBackbone = root.Backbone;
// Create a local reference to splice.
var splice = Array.prototype.splice;
// Create a local reference to array methods.
var ArrayProto = Array.prototype;
var slice = ArrayProto.slice;
var splice = ArrayProto.splice;
// The top-level namespace. All public Backbone classes and modules will
// be attached to this. Exported for both CommonJS and the browser.
@@ -866,7 +868,9 @@
// Mix in each Underscore method as a proxy to `Collection#models`.
_.each(methods, function(method) {
Collection.prototype[method] = function() {
return _[method].apply(_, [this.models].concat(_.toArray(arguments)));
var args = slice.call(arguments);
args.unshift(this.models);
return _[method].apply(_, args);
};
});
@@ -961,9 +965,12 @@
this.history = options && options.history || root.history;
};
// Cached regex for cleaning leading hashes and slashes .
// Cached regex for cleaning leading hashes and slashes.
var routeStripper = /^[#\/]/;
// Cached regex for stripping leading and trailing slashes.
var rootStripper = /^\/+|\/+$/g;
// Cached regex for detecting MSIE.
var isExplorer = /msie [\w.]+/;
@@ -993,7 +1000,7 @@
if (fragment == null) {
if (this._hasPushState || !this._wantsHashChange || forcePushState) {
fragment = this.location.pathname;
var root = this.options.root.replace(trailingSlash, '');
var root = this.root.replace(trailingSlash, '');
if (!fragment.indexOf(root)) fragment = fragment.substr(root.length);
} else {
fragment = this.getHash();
@@ -1011,6 +1018,7 @@
// Figure out the initial configuration. Do we need an iframe?
// Is pushState desired ... is it available?
this.options = _.extend({}, {root: '/'}, this.options, options);
this.root = this.options.root;
this._wantsHashChange = this.options.hashChange !== false;
this._wantsPushState = !!this.options.pushState;
this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState);
@@ -1018,8 +1026,8 @@
var docMode = document.documentMode;
var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
// Normalize root to always include trailing slash
if (!trailingSlash.test(this.options.root)) this.options.root += '/';
// Normalize root to always include a leading and trailing slash.
this.root = ('/' + this.root + '/').replace(rootStripper, '/');
if (oldIE && this._wantsHashChange) {
this.iframe = Backbone.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
@@ -1040,13 +1048,13 @@
// opened by a non-pushState browser.
this.fragment = fragment;
var loc = this.location;
var atRoot = (loc.pathname.replace(/[^/]$/, '$&/') === this.options.root) && !loc.search;
var atRoot = (loc.pathname.replace(/[^/]$/, '$&/') === this.root) && !loc.search;
// If we've started off with a route from a `pushState`-enabled browser,
// but we're currently in a browser that doesn't support it...
if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) {
this.fragment = this.getFragment(null, true);
this.location.replace(this.options.root + this.location.search + '#' + this.fragment);
this.location.replace(this.root + this.location.search + '#' + this.fragment);
// Return immediately as browser will do redirect to new url
return true;
@@ -1054,7 +1062,7 @@
// in a browser where it could be `pushState`-based instead...
} else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
this.fragment = this.getHash().replace(routeStripper, '');
this.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
this.history.replaceState({}, document.title, this.root + this.fragment);
}
if (!this.options.silent) return this.loadUrl();
@@ -1113,7 +1121,7 @@
var frag = (fragment || '').replace(routeStripper, '');
if (this.fragment === frag) return;
this.fragment = frag;
var url = (frag.indexOf(this.options.root) !== 0 ? this.options.root : '') + frag;
var url = (frag.indexOf(this.root) !== 0 ? this.root : '') + frag;
// If pushState is available, we use it to set the fragment as a real URL.
if (this._hasPushState) {
@@ -1434,7 +1442,7 @@
return child;
};
// Set up inheritance for the model, collection, and view.
// Set up inheritance for the model, collection, router, and view.
Model.extend = Collection.extend = Router.extend = View.extend = extend;
// Throw an error when a URL is needed, and none is supplied.

View File

@@ -344,7 +344,7 @@ $(document).ready(function() {
history: {
pushState: function(state, title, url) {},
replaceState: function(state, title, url) {
strictEqual(url, 'http://example.com/root/fragment');
strictEqual(url, '/root/fragment');
}
}
});
@@ -365,4 +365,88 @@ $(document).ready(function() {
});
});
test("Normalize root - leading slash.", 1, function() {
Backbone.history.stop();
location.replace('http://example.com/root');
Backbone.history = new Backbone.History({
location: location,
history: {
pushState: function(){},
replaceState: function(){}
}
});
Backbone.history.start({root: 'root'});
strictEqual(Backbone.history.root, '/root/');
});
test("Transition from hashChange to pushState.", 1, function() {
Backbone.history.stop();
location.replace('http://example.com/root#x/y');
Backbone.history = new Backbone.History({
location: location,
history: {
pushState: function(){},
replaceState: function(state, title, url){
strictEqual(url, '/root/x/y');
}
}
});
Backbone.history.start({
root: 'root',
pushState: true
});
});
test("#1619: Router: Normalize empty root", 1, function() {
Backbone.history.stop();
location.replace('http://example.com/');
Backbone.history = new Backbone.History({
location: location,
history: {
pushState: function(){},
replaceState: function(){}
}
});
Backbone.history.start({root: ''});
strictEqual(Backbone.history.root, '/');
});
test("#1619: Router: nagivate with empty root", 1, function() {
Backbone.history.stop();
location.replace('http://example.com/');
Backbone.history = new Backbone.History({
location: location,
history: {
pushState: function(state, title, url) {
strictEqual(url, '/fragment');
}
}
});
Backbone.history.start({
pushState: true,
root: '',
hashChange: false
});
Backbone.history.navigate('fragment');
});
test("Transition from pushState to hashChange.", 1, function() {
Backbone.history.stop();
location.replace('http://example.com/root/x/y?a=b');
location.replace = function(url) {
strictEqual(url, '/root/?a=b#x/y');
};
Backbone.history = new Backbone.History({
location: location,
history: {
pushState: null,
replaceState: null
}
});
Backbone.history.start({
root: 'root',
pushState: true
});
});
});

204
vendor/docdown/src/DocDown/Alias.php vendored Normal file
View File

@@ -0,0 +1,204 @@
<?php
/**
* A class to represent a JSDoc entry alias.
*/
class Alias {
/**
* The alias owner.
*
* @memberOf Alias
* @type Object
*/
public $owner;
/*--------------------------------------------------------------------------*/
/**
* The Alias constructor.
*
* @constructor
* @param {String} $name The alias name.
* @param {Object} $owner The alias owner.
*/
public function __construct($name, $owner) {
$this->owner = $owner;
$this->_name = $name;
$this->_call = $owner->getCall();
$this->_desc = $owner->getDesc();
$this->_example = $owner->getExample();
$this->_lineNumber = $owner->getLineNumber();
$this->_members = $owner->getMembers();
$this->_params = $owner->getParams();
$this->_returns = $owner->getReturns();
$this->_type = $owner->getType();
$this->_isCtor = $owner->isCtor();
$this->_isPlugin = $owner->isPlugin();
$this->_isPrivate = $owner->isPrivate();
$this->_isStatic = $owner->isStatic();
}
/*--------------------------------------------------------------------------*/
/**
* Extracts the entry's `alias` objects.
*
* @memberOf Alias
* @param {Number} $index The index of the array value to return.
* @returns {Array|String} The entry's `alias` objects.
*/
public function getAliases( $index = null ) {
$result = array();
return $index !== null
? @$result[$index]
: $result;
}
/**
* Extracts the function call from the owner entry.
*
* @memberOf Alias
* @returns {String} The function call.
*/
public function getCall() {
return $this->_call;
}
/**
* Extracts the owner entry's description.
*
* @memberOf Alias
* @returns {String} The owner entry's description.
*/
public function getDesc() {
return $this->_desc;
}
/**
* Extracts the owner entry's `example` data.
*
* @memberOf Alias
* @returns {String} The owner entry's `example` data.
*/
public function getExample() {
return $this->_example;
}
/**
* Resolves the owner entry's line number.
*
* @memberOf Alias
* @returns {Number} The owner entry's line number.
*/
public function getLineNumber() {
return $this->_lineNumber;
}
/**
* Extracts the owner entry's `member` data.
*
* @memberOf Alias
* @param {Number} $index The index of the array value to return.
* @returns {Array|String} The owner entry's `member` data.
*/
public function getMembers( $index = null ) {
return $index !== null
? @$this->_members[$index]
: $this->_members;
}
/**
* Extracts the owner entry's `name` data.
*
* @memberOf Alias
* @returns {String} The owner entry's `name` data.
*/
public function getName() {
return $this->_name;
}
/**
* Extracts the owner entry's `param` data.
*
* @memberOf Alias
* @param {Number} $index The index of the array value to return.
* @returns {Array} The owner entry's `param` data.
*/
public function getParams( $index = null ) {
return $index !== null
? @$this->_params[$index]
: $this->_params;
}
/**
* Extracts the owner entry's `returns` data.
*
* @memberOf Alias
* @returns {String} The owner entry's `returns` data.
*/
public function getReturns() {
return $this->_returns;
}
/**
* Extracts the owner entry's `type` data.
*
* @memberOf Alias
* @returns {String} The owner entry's `type` data.
*/
public function getType() {
return $this->_type;
}
/**
* Checks if the entry is an alias.
*
* @memberOf Alias
* @returns {Boolean} Returns `true`.
*/
public function isAlias() {
return true;
}
/**
* Checks if the owner entry is a constructor.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if a constructor, else `false`.
*/
public function isCtor() {
return $this->_isCtor;
}
/**
* Checks if the owner entry *is* assigned to a prototype.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
*/
public function isPlugin() {
return $this->_isPlugin;
}
/**
* Checks if the owner entry is private.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if private, else `false`.
*/
public function isPrivate() {
return $this->_isPrivate;
}
/**
* Checks if the owner entry is *not* assigned to a prototype.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
*/
public function isStatic() {
return $this->_isStatic;
}
}
?>

View File

@@ -1,5 +1,7 @@
<?php
require(dirname(__FILE__) . "/Alias.php");
/**
* A class to simplify parsing a single JSDoc entry.
*/
@@ -37,7 +39,7 @@ class Entry {
* @constructor
* @param {String} $entry The documentation entry to analyse.
* @param {String} $source The source code.
* @param {String} $lang The language highlighter used for code examples.
* @param {String} [$lang ='js'] The language highlighter used for code examples.
*/
public function __construct( $entry, $source, $lang = 'js' ) {
$this->entry = $entry;
@@ -70,16 +72,45 @@ class Entry {
* @returns {Boolean} Returns `true` if the entry is a function reference, else `false`.
*/
private function isFunction() {
return !!(
$this->isCtor() ||
count($this->getParams()) ||
count($this->getReturns()) ||
preg_match('/\*\s*@function\b/', $this->entry)
);
if (!isset($this->_isFunction)) {
$this->_isFunction = !!(
$this->isCtor() ||
count($this->getParams()) ||
count($this->getReturns()) ||
preg_match('/\*\s*@function\b/', $this->entry)
);
}
return $this->_isFunction;
}
/*--------------------------------------------------------------------------*/
/**
* Extracts the entry's `alias` objects.
*
* @memberOf Entry
* @param {Number} $index The index of the array value to return.
* @returns {Array|String} The entry's `alias` objects.
*/
public function getAliases( $index = null ) {
if (!isset($this->_aliases)) {
preg_match('#\*\s*@alias\s+([^\n]+)#', $this->entry, $result);
if (count($result)) {
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
$result = preg_split('/,\s*/', $result);
foreach ($result as $resultIndex => $value) {
$result[$resultIndex] = new Alias($value, $this);
}
}
$this->_aliases = $result;
}
return $index !== null
? @$this->_aliases[$index]
: $this->_aliases;
}
/**
* Extracts the function call from the entry.
*
@@ -87,6 +118,10 @@ class Entry {
* @returns {String} The function call.
*/
public function getCall() {
if (isset($this->_call)) {
return $this->_call;
}
preg_match('#\*/\s*(?:function ([^(]*)|(.*?)(?=[:=,]|return\b))#', $this->entry, $result);
if ($result = array_pop($result)) {
$result = array_pop(explode('var ', trim(trim(array_pop(explode('.', $result))), "'")));
@@ -111,176 +146,239 @@ class Entry {
$result = $name .'('. implode(array_slice($result, 1), ', ') .')';
$result = str_replace(', [', ' [, ', str_replace('], [', ', ', $result));
}
return $result ? $result : $name;
$this->_call = $result ? $result : $name;
return $this->_call;
}
/**
* Extracts the entry description.
* Extracts the entry's description.
*
* @memberOf Entry
* @returns {String} The entry description.
* @returns {String} The entry's description.
*/
public function getDesc() {
if (isset($this->_desc)) {
return $this->_desc;
}
preg_match('#/\*\*(?:\s*\*)?([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
if (count($result)) {
$type = $this->getType();
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
$result = ($type == 'Function' ? '' : '(' . str_replace('|', ', ', trim($type, '{}')) . '): ') . $result;
}
$this->_desc = $result;
return $result;
}
/**
* Extracts the entry `example` data.
* Extracts the entry's `example` data.
*
* @memberOf Entry
* @returns {String} The entry `example` data.
* @returns {String} The entry's `example` data.
*/
public function getExample() {
if (isset($this->_example)) {
return $this->_example;
}
preg_match('#\*\s*@example\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
if (count($result)) {
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', "\n", $result[1]));
$result = '```' . $this->lang . "\n" . $result . "\n```";
}
$this->_example = $result;
return $result;
}
/**
* Resolves the line number of the entry.
* Resolves the entry's line number.
*
* @memberOf Entry
* @returns {Number} The line number.
* @returns {Number} The entry's line number.
*/
public function getLineNumber() {
preg_match_all('/\n/', substr($this->source, 0, strrpos($this->source, $this->entry) + strlen($this->entry)), $lines);
return count(array_pop($lines)) + 1;
if (!isset($this->_lineNumber)) {
preg_match_all('/\n/', substr($this->source, 0, strrpos($this->source, $this->entry) + strlen($this->entry)), $lines);
$this->_lineNumber = count(array_pop($lines)) + 1;
}
return $this->_lineNumber;
}
/**
* Extracts the entry `member` data.
* Extracts the entry's `member` data.
*
* @memberOf Entry
* @param {Number} $index The index of the array value to return.
* @returns {Array|String} The entry `member` data.
* @returns {Array|String} The entry's `member` data.
*/
public function getMembers( $index = null ) {
preg_match('#\*\s*@member(?:Of)?\s+([^\n]+)#', $this->entry, $result);
if (count($result)) {
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
$result = preg_split('/,\s*/', $result);
if (!isset($this->_members)) {
preg_match('#\*\s*@member(?:Of)?\s+([^\n]+)#', $this->entry, $result);
if (count($result)) {
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
$result = preg_split('/,\s*/', $result);
}
$this->_members = $result;
}
return $index !== null ? @$result[$index] : $result;
return $index !== null
? @$this->_members[$index]
: $this->_members;
}
/**
* Extracts the entry `name` data.
* Extracts the entry's `name` data.
*
* @memberOf Entry
* @returns {String} The entry `name` data.
* @returns {String} The entry's `name` data.
*/
public function getName() {
if (isset($this->_name)) {
return $this->_name;
}
preg_match('#\*\s*@name\s+([^\n]+)#', $this->entry, $result);
if (count($result)) {
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
} else {
$result = array_shift(explode('(', $this->getCall()));
}
$this->_name = $result;
return $result;
}
/**
* Extracts the entry `param` data.
* Extracts the entry's `param` data.
*
* @memberOf Entry
* @param {Number} $index The index of the array value to return.
* @returns {Array} The entry `param` data.
* @returns {Array} The entry's `param` data.
*/
public function getParams( $index = null ) {
preg_match_all('#\*\s*@param\s+\{([^}]+)\}\s+(\[.+\]|[$\w|]+(?:\[.+\])?)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $result);
if (count($result = array_filter(array_slice($result, 1)))) {
// repurpose array
foreach ($result as $param) {
foreach ($param as $key => $value) {
if (!is_array($result[0][$key])) {
$result[0][$key] = array();
if (!isset($this->_params)) {
preg_match_all('#\*\s*@param\s+\{([^}]+)\}\s+(\[.+\]|[$\w|]+(?:\[.+\])?)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $result);
if (count($result = array_filter(array_slice($result, 1)))) {
// repurpose array
foreach ($result as $param) {
foreach ($param as $key => $value) {
if (!is_array($result[0][$key])) {
$result[0][$key] = array();
}
$result[0][$key][] = trim(preg_replace('/(?:^|\n)\s*\* */', ' ', $value));
}
$result[0][$key][] = trim(preg_replace('/(?:^|\n)\s*\* */', ' ', $value));
}
$result = $result[0];
}
$result = $result[0];
$this->_params = $result;
}
return $index !== null ? @$result[$index] : $result;
return $index !== null
? @$this->_params[$index]
: $this->_params;
}
/**
* Extracts the entry `returns` data.
* Extracts the entry's `returns` data.
*
* @memberOf Entry
* @returns {String} The entry `returns` data.
* @returns {String} The entry's `returns` data.
*/
public function getReturns() {
if (isset($this->_returns)) {
return $this->_returns;
}
preg_match('#\*\s*@returns\s+\{([^}]+)\}\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
if (count($result)) {
$result = array_map('trim', array_slice($result, 1));
$result[0] = str_replace('|', ', ', $result[0]);
$result[1] = preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]);
}
$this->_returns = $result;
return $result;
}
/**
* Extracts the entry `type` data.
* Extracts the entry's `type` data.
*
* @memberOf Entry
* @returns {String} The entry `type` data.
* @returns {String} The entry's `type` data.
*/
public function getType() {
if (isset($this->_type)) {
return $this->_type;
}
preg_match('#\*\s*@type\s+([^\n]+)#', $this->entry, $result);
if (count($result)) {
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
} else {
$result = $this->isFunction() ? 'Function' : 'Unknown';
}
$this->_type = $result;
return $result;
}
/**
* Checks if an entry is a constructor.
* Checks if the entry is an alias.
*
* @memberOf Entry
* @returns {Boolean} Returns true if a constructor, else false.
* @returns {Boolean} Returns `false`.
*/
public function isAlias() {
return false;
}
/**
* Checks if the entry is a constructor.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if a constructor, else `false`.
*/
public function isCtor() {
return !!preg_match('/\*\s*@constructor\b/', $this->entry);
if (!isset($this->_isCtor)) {
$this->_isCtor = !!preg_match('/\*\s*@constructor\b/', $this->entry);
}
return $this->_isCtor;
}
/**
* Checks if an entry *is* assigned to a prototype.
* Checks if the entry *is* assigned to a prototype.
*
* @memberOf Entry
* @returns {Boolean} Returns true if assigned to a prototype, else false.
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
*/
public function isPlugin() {
return !$this->isCtor() && !$this->isPrivate() && !$this->isStatic();
if (!isset($this->_isPlugin)) {
$this->_isPlugin = !$this->isCtor() && !$this->isPrivate() && !$this->isStatic();
}
return $this->_isPlugin;
}
/**
* Checks if an entry is private.
* Checks if the entry is private.
*
* @memberOf Entry
* @returns {Boolean} Returns true if private, else false.
* @returns {Boolean} Returns `true` if private, else `false`.
*/
public function isPrivate() {
return !!preg_match('/\*\s*@private\b/', $this->entry) || strrpos($this->entry, '@') === false;
if (!isset($this->_isPrivate)) {
$this->_isPrivate = !!preg_match('/\*\s*@private\b/', $this->entry) || strrpos($this->entry, '@') === false;
}
return $this->_isPrivate;
}
/**
* Checks if an entry is *not* assigned to a prototype.
* Checks if the entry is *not* assigned to a prototype.
*
* @memberOf Entry
* @returns {Boolean} Returns true if not assigned to a prototype, else false.
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
*/
public function isStatic() {
if (isset($this->_isStatic)) {
return $this->_isStatic;
}
$public = !$this->isPrivate();
$result = $public && !!preg_match('/\*\s*@static\b/', $this->entry);
@@ -298,6 +396,7 @@ class Entry {
$result = true;
}
}
$this->_isStatic = $result;
return $result;
}
}

View File

@@ -221,22 +221,39 @@ class Generator {
foreach ($members as $member) {
// create api category arrays
if (!isset($api[$member]) && $member) {
// create temporary entry to be replaced later
$api[$member] = new Entry('', '', $entry->lang);
$api[$member]->static = array();
$api[$member]->plugin = array();
}
// append entry to api category
if (!$member || $entry->isCtor() || ($entry->getType() == 'Object' &&
!preg_match('/[=:]\s*null\s*[,;]?$/', $entry->entry))) {
// assign the real entry, replacing the temporary entry if it exist
$member = ($member ? $member . ($entry->isPlugin() ? '#' : '.') : '') . $name;
$entry->static = @$api[$member] ? $api[$member]->static : array();
$entry->plugin = @$api[$member] ? $api[$member]->plugin : array();
$api[$member] = $entry;
$api[$member] = $entry;
foreach ($entry->getAliases() as $alias) {
$api[$member] = $alias;
$alias->static = array();
$alias->plugin = array();
}
}
else if ($entry->isStatic()) {
$api[$member]->static[] = $entry;
} else if (!$entry->isCtor()) {
foreach ($entry->getAliases() as $alias) {
$api[$member]->static[] = $alias;
}
}
else if (!$entry->isCtor()) {
$api[$member]->plugin[] = $entry;
foreach ($entry->getAliases() as $alias) {
$api[$member]->plugin[] = $alias;
}
}
}
}
@@ -346,6 +363,11 @@ class Generator {
$result[] = $openTag;
foreach ($api as $entry) {
// skip aliases
if ($entry->isAlias()) {
continue;
}
// add root entry
$member = $entry->member . $entry->getName();
$compiling = $compiling ? ($result[] = $closeTag) : true;
@@ -370,6 +392,11 @@ class Generator {
// body
foreach ($subentries as $subentry) {
// skip aliases
if ($subentry->isAlias()) {
continue;
}
// description
array_push(
$result,
@@ -377,6 +404,14 @@ class Generator {
Generator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [&#x24C8;](#{href} \"View in source\") [&#x24C9;][1]\n\n#{desc}", $subentry)
);
// @alias
if (count($aliases = $subentry->getAliases())) {
array_push($result, '', '#### Aliases');
foreach ($aliases as $index => $alias) {
$aliases[$index] = $alias->getName();
}
$result[] = implode(', ', $aliases);
}
// @param
if (count($params = $subentry->getParams())) {
array_push($result, '', '#### Arguments');

View File

@@ -1,4 +1,4 @@
[QUnit](http://docs.jquery.com/QUnit) - A JavaScript Unit Testing framework.
[QUnit](http://qunitjs.com) - A JavaScript Unit Testing framework.
================================
QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery
@@ -35,7 +35,8 @@ the change, run `grunt` to lint and test it, then commit, push and create a pull
Include some background for the change in the commit message and `Fixes #nnn`, referring
to the issue number you're addressing.
To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`.
To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`. That gives you a global
grunt binary. For additional grunt tasks, also run `npm install`.
Releases
--------
@@ -47,3 +48,12 @@ tag, update them again to the next version, commit and push commits and tags
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
or whitespace cleanups.
To upload to code.jquery.com (replace $version accordingly):
scp -q qunit/qunit.js jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/qunit/qunit-$version.js
scp -q qunit/qunit.css jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/qunit/qunit-$version.css
Then update /var/www/html/code.jquery.com/index.html and purge it with:
curl -s http://code.origin.jquery.com/?reload

View File

@@ -1,11 +1,11 @@
/**
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
* http://qunitjs.com
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
* Copyright 2012 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
/** Font Family and Sizes */
@@ -20,7 +20,7 @@
/** Resets */
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
margin: 0;
padding: 0;
}
@@ -67,6 +67,7 @@
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
overflow: hidden;
}
#qunit-userAgent {
@@ -76,6 +77,9 @@
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
#qunit-modulefilter-container {
float: right;
}
/** Tests: Pass/Fail */

View File

@@ -1,11 +1,11 @@
/**
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
* http://qunitjs.com
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
* Copyright 2012 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
(function( window ) {
@@ -17,6 +17,8 @@ var QUnit,
fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty,
// Keep a local reference to Date (GH-283)
Date = window.Date,
defined = {
setTimeout: typeof window.setTimeout !== "undefined",
sessionStorage: (function() {
@@ -304,7 +306,8 @@ QUnit = {
// call on start of module test to prepend name to all tests
module: function( name, testEnvironment ) {
config.currentModule = name;
config.currentModuleTestEnviroment = testEnvironment;
config.currentModuleTestEnvironment = testEnvironment;
config.modules[name] = true;
},
asyncTest: function( testName, expected, callback ) {
@@ -336,7 +339,7 @@ QUnit = {
async: async,
callback: callback,
module: config.currentModule,
moduleTestEnvironment: config.currentModuleTestEnviroment,
moduleTestEnvironment: config.currentModuleTestEnvironment,
stack: sourceFromStacktrace( 2 )
});
@@ -349,7 +352,11 @@ QUnit = {
// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
expect: function( asserts ) {
config.current.expected = asserts;
if (arguments.length === 1) {
config.current.expected = asserts;
} else {
return config.current.expected;
}
},
start: function( count ) {
@@ -415,6 +422,8 @@ QUnit.assert = {
var source,
details = {
module: config.current.module,
name: config.current.testName,
result: result,
message: msg
};
@@ -600,6 +609,9 @@ config = {
}
],
// Set of all modules.
modules: {},
// logging callback queues
begin: [],
done: [],
@@ -710,17 +722,10 @@ extend( QUnit, {
},
// Resets the test setup. Useful for tests that modify the DOM.
// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
reset: function() {
var fixture;
if ( window.jQuery ) {
jQuery( "#qunit-fixture" ).html( config.fixture );
} else {
fixture = id( "qunit-fixture" );
if ( fixture ) {
fixture.innerHTML = config.fixture;
}
var fixture = id( "qunit-fixture" );
if ( fixture ) {
fixture.innerHTML = config.fixture;
}
},
@@ -781,6 +786,8 @@ extend( QUnit, {
var output, source,
details = {
module: config.current.module,
name: config.current.testName,
result: result,
message: message,
actual: actual,
@@ -826,6 +833,8 @@ extend( QUnit, {
var output,
details = {
module: config.current.module,
name: config.current.testName,
result: false,
message: message
};
@@ -916,7 +925,9 @@ QUnit.load = function() {
runLoggingCallbacks( "begin", QUnit, {} );
// Initialize the config, saving the execution queue
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes,
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter,
numModules = 0,
moduleFilterHtml = "",
urlConfigHtml = "",
oldconfig = extend( {}, config );
@@ -940,6 +951,15 @@ QUnit.load = function() {
urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>";
}
moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( config.module === undefined ? "selected" : "" ) + ">< All Modules ></option>";
for ( i in config.modules ) {
if ( config.modules.hasOwnProperty( i ) ) {
numModules += 1;
moduleFilterHtml += "<option value='" + encodeURIComponent(i) + "' " + ( config.module === i ? "selected" : "" ) + ">" + i + "</option>";
}
}
moduleFilterHtml += "</select>";
// `userAgent` initialized at top of scope
userAgent = id( "qunit-userAgent" );
if ( userAgent ) {
@@ -1002,6 +1022,19 @@ QUnit.load = function() {
window.location = QUnit.url( params );
});
toolbar.appendChild( urlConfigCheckboxes );
if (numModules > 1) {
moduleFilter = document.createElement( 'span' );
moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
moduleFilter.innerHTML = moduleFilterHtml;
addEvent( moduleFilter, "change", function() {
var selectBox = moduleFilter.getElementsByTagName("select")[0],
selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
});
toolbar.appendChild(moduleFilter);
}
}
// `main` initialized at top of scope
@@ -1039,9 +1072,9 @@ window.onerror = function ( error, filePath, linerNr ) {
}
QUnit.pushFailure( error, filePath + ":" + linerNr );
} else {
QUnit.test( "global failure", function() {
QUnit.test( "global failure", extend( function() {
QUnit.pushFailure( error, filePath + ":" + linerNr );
});
}, { validTest: validTest } ) );
}
return false;
}
@@ -1108,6 +1141,11 @@ function done() {
}
}
// scroll back to top to show results
if ( window.scrollTo ) {
window.scrollTo(0, 0);
}
runLoggingCallbacks( "done", QUnit, {
failed: config.stats.bad,
passed: passed,
@@ -1123,6 +1161,12 @@ function validTest( test ) {
module = config.module && config.module.toLowerCase(),
fullName = (test.module + ": " + test.testName).toLowerCase();
// Internally-generated tests are always valid
if ( test.callback && test.callback.validTest === validTest ) {
delete test.callback.validTest;
return true;
}
if ( config.testNumber ) {
return test.testNumber === config.testNumber;
}
@@ -1404,7 +1448,8 @@ QUnit.equiv = (function() {
a.global === b.global &&
// (gmi) ...
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline;
a.multiline === b.multiline &&
a.sticky === b.sticky;
},
// - skip when the property is a method of an instance (OOP)

View File

@@ -14,6 +14,12 @@ $(document).ready(function() {
});
test("#750 - Return _ instance.", 2, function() {
var instance = _([]);
ok(_(instance) === instance);
ok(new _(instance) === instance);
});
test("utility: identity", function() {
var moe = {name : 'moe'};
equal(_.identity(moe), moe, 'moe is the same as his identity');
@@ -229,4 +235,10 @@ $(document).ready(function() {
templateEscaped({f: function(){ ok(!(countEscaped++)); }});
});
test('#746 - _.template settings are not modified.', 1, function() {
var settings = {};
_.template('', null, settings);
deepEqual(settings, {});
});
});

View File

@@ -1,11 +1,11 @@
/**
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
* http://qunitjs.com
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
* Copyright 2012 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
/** Font Family and Sizes */
@@ -20,7 +20,7 @@
/** Resets */
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
margin: 0;
padding: 0;
}
@@ -38,10 +38,10 @@
line-height: 1em;
font-weight: normal;
border-radius: 15px 15px 0 0;
-moz-border-radius: 15px 15px 0 0;
-webkit-border-top-right-radius: 15px;
-webkit-border-top-left-radius: 15px;
border-radius: 5px 5px 0 0;
-moz-border-radius: 5px 5px 0 0;
-webkit-border-top-right-radius: 5px;
-webkit-border-top-left-radius: 5px;
}
#qunit-header a {
@@ -54,9 +54,9 @@
color: #fff;
}
#qunit-header label {
#qunit-testrunner-toolbar label {
display: inline-block;
padding-left: 0.5em;
padding: 0 .5em 0 .1em;
}
#qunit-banner {
@@ -67,6 +67,7 @@
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
overflow: hidden;
}
#qunit-userAgent {
@@ -76,6 +77,9 @@
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
#qunit-modulefilter-container {
float: right;
}
/** Tests: Pass/Fail */
@@ -113,13 +117,9 @@
background-color: #fff;
border-radius: 15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
box-shadow: inset 0px 2px 13px #999;
-moz-box-shadow: inset 0px 2px 13px #999;
-webkit-box-shadow: inset 0px 2px 13px #999;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
#qunit-tests table {
@@ -162,8 +162,7 @@
#qunit-tests b.failed { color: #710909; }
#qunit-tests li li {
margin: 0.5em;
padding: 0.4em 0.5em 0.4em 0.5em;
padding: 5px;
background-color: #fff;
border-bottom: none;
list-style-position: inside;
@@ -172,9 +171,9 @@
/*** Passing Styles */
#qunit-tests li li.pass {
color: #5E740B;
color: #3c510c;
background-color: #fff;
border-left: 26px solid #C6E746;
border-left: 10px solid #C6E746;
}
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
@@ -190,15 +189,15 @@
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
border-left: 26px solid #EE5757;
border-left: 10px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 15px 15px;
-moz-border-radius: 0 0 15px 15px;
-webkit-border-bottom-right-radius: 15px;
-webkit-border-bottom-left-radius: 15px;
border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
}
#qunit-tests .fail { color: #000000; background-color: #EE5757; }

View File

@@ -1,11 +1,11 @@
/**
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
* http://qunitjs.com
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
* Copyright 2012 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
(function( window ) {
@@ -17,6 +17,8 @@ var QUnit,
fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty,
// Keep a local reference to Date (GH-283)
Date = window.Date,
defined = {
setTimeout: typeof window.setTimeout !== "undefined",
sessionStorage: (function() {
@@ -304,7 +306,8 @@ QUnit = {
// call on start of module test to prepend name to all tests
module: function( name, testEnvironment ) {
config.currentModule = name;
config.currentModuleTestEnviroment = testEnvironment;
config.currentModuleTestEnvironment = testEnvironment;
config.modules[name] = true;
},
asyncTest: function( testName, expected, callback ) {
@@ -336,7 +339,7 @@ QUnit = {
async: async,
callback: callback,
module: config.currentModule,
moduleTestEnvironment: config.currentModuleTestEnviroment,
moduleTestEnvironment: config.currentModuleTestEnvironment,
stack: sourceFromStacktrace( 2 )
});
@@ -349,7 +352,11 @@ QUnit = {
// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
expect: function( asserts ) {
config.current.expected = asserts;
if (arguments.length === 1) {
config.current.expected = asserts;
} else {
return config.current.expected;
}
},
start: function( count ) {
@@ -403,6 +410,8 @@ QUnit = {
QUnit.assert = {
/**
* Asserts rough true-ish result.
* @name ok
* @function
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
*/
ok: function( result, msg ) {
@@ -413,6 +422,8 @@ QUnit.assert = {
var source,
details = {
module: config.current.module,
name: config.current.testName,
result: result,
message: msg
};
@@ -437,36 +448,59 @@ QUnit.assert = {
/**
* Assert that the first two arguments are equal, with an optional message.
* Prints out both actual and expected values.
* @name equal
* @function
* @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
*/
equal: function( actual, expected, message ) {
QUnit.push( expected == actual, actual, expected, message );
},
/**
* @name notEqual
* @function
*/
notEqual: function( actual, expected, message ) {
QUnit.push( expected != actual, actual, expected, message );
},
/**
* @name deepEqual
* @function
*/
deepEqual: function( actual, expected, message ) {
QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
},
/**
* @name notDeepEqual
* @function
*/
notDeepEqual: function( actual, expected, message ) {
QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
},
/**
* @name strictEqual
* @function
*/
strictEqual: function( actual, expected, message ) {
QUnit.push( expected === actual, actual, expected, message );
},
/**
* @name notStrictEqual
* @function
*/
notStrictEqual: function( actual, expected, message ) {
QUnit.push( expected !== actual, actual, expected, message );
},
raises: function( block, expected, message ) {
throws: function( block, expected, message ) {
var actual,
ok = false;
// 'expected' is optional
if ( typeof expected === "string" ) {
message = expected;
expected = null;
@@ -494,18 +528,29 @@ QUnit.assert = {
} else if ( expected.call( {}, actual ) === true ) {
ok = true;
}
}
QUnit.push( ok, actual, null, message );
QUnit.push( ok, actual, null, message );
} else {
QUnit.pushFailure( message, null, 'No exception was thrown.' );
}
}
};
// @deprecated: Kept assertion helpers in root for backwards compatibility
/**
* @deprecate since 1.8.0
* Kept assertion helpers in root for backwards compatibility
*/
extend( QUnit, QUnit.assert );
/**
* @deprecated: Kept for backwards compatibility
* next step: remove entirely
* @deprecated since 1.9.0
* Kept global "raises()" for backwards compatibility
*/
QUnit.raises = QUnit.assert.throws;
/**
* @deprecated since 1.0.0, replaced with error pushes since 1.3.0
* Kept to avoid TypeErrors for undefined methods.
*/
QUnit.equals = function() {
QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
@@ -549,7 +594,23 @@ config = {
// when enabled, all tests must call expect()
requireExpects: false,
urlConfig: [ "noglobals", "notrycatch" ],
// add checkboxes that are persisted in the query-string
// when enabled, the id is set to `true` as a `QUnit.config` property
urlConfig: [
{
id: "noglobals",
label: "Check for Globals",
tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
},
{
id: "notrycatch",
label: "No try-catch",
tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
}
],
// Set of all modules.
modules: {},
// logging callback queues
begin: [],
@@ -661,17 +722,10 @@ extend( QUnit, {
},
// Resets the test setup. Useful for tests that modify the DOM.
// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
reset: function() {
var fixture;
if ( window.jQuery ) {
jQuery( "#qunit-fixture" ).html( config.fixture );
} else {
fixture = id( "qunit-fixture" );
if ( fixture ) {
fixture.innerHTML = config.fixture;
}
var fixture = id( "qunit-fixture" );
if ( fixture ) {
fixture.innerHTML = config.fixture;
}
},
@@ -732,6 +786,8 @@ extend( QUnit, {
var output, source,
details = {
module: config.current.module,
name: config.current.testName,
result: result,
message: message,
actual: actual,
@@ -770,26 +826,36 @@ extend( QUnit, {
});
},
pushFailure: function( message, source ) {
pushFailure: function( message, source, actual ) {
if ( !config.current ) {
throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
}
var output,
details = {
module: config.current.module,
name: config.current.testName,
result: false,
message: message
};
message = escapeInnerText(message ) || "error";
message = escapeInnerText( message ) || "error";
message = "<span class='test-message'>" + message + "</span>";
output = message;
output += "<table>";
if ( actual ) {
output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeInnerText( actual ) + "</pre></td></tr>";
}
if ( source ) {
details.source = source;
output += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr></table>";
output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr>";
}
output += "</table>";
runLoggingCallbacks( "log", QUnit, details );
config.current.assertions.push({
@@ -859,7 +925,9 @@ QUnit.load = function() {
runLoggingCallbacks( "begin", QUnit, {} );
// Initialize the config, saving the execution queue
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter,
numModules = 0,
moduleFilterHtml = "",
urlConfigHtml = "",
oldconfig = extend( {}, config );
@@ -872,10 +940,26 @@ QUnit.load = function() {
for ( i = 0; i < len; i++ ) {
val = config.urlConfig[i];
config[val] = QUnit.urlParams[val];
urlConfigHtml += "<label><input name='" + val + "' type='checkbox'" + ( config[val] ? " checked='checked'" : "" ) + ">" + val + "</label>";
if ( typeof val === "string" ) {
val = {
id: val,
label: val,
tooltip: "[no tooltip available]"
};
}
config[ val.id ] = QUnit.urlParams[ val.id ];
urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>";
}
moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( config.module === undefined ? "selected" : "" ) + ">< All Modules ></option>";
for ( i in config.modules ) {
if ( config.modules.hasOwnProperty( i ) ) {
numModules += 1;
moduleFilterHtml += "<option value='" + encodeURIComponent(i) + "' " + ( config.module === i ? "selected" : "" ) + ">" + i + "</option>";
}
}
moduleFilterHtml += "</select>";
// `userAgent` initialized at top of scope
userAgent = id( "qunit-userAgent" );
if ( userAgent ) {
@@ -885,12 +969,7 @@ QUnit.load = function() {
// `banner` initialized at top of scope
banner = id( "qunit-header" );
if ( banner ) {
banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined }) + "'>" + banner.innerHTML + "</a> " + urlConfigHtml;
addEvent( banner, "change", function( event ) {
var params = {};
params[ event.target.name ] = event.target.checked ? true : undefined;
window.location = QUnit.url( params );
});
banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
}
// `toolbar` initialized at top of scope
@@ -931,8 +1010,31 @@ QUnit.load = function() {
// `label` initialized at top of scope
label = document.createElement( "label" );
label.setAttribute( "for", "qunit-filter-pass" );
label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." );
label.innerHTML = "Hide passed tests";
toolbar.appendChild( label );
urlConfigCheckboxes = document.createElement( 'span' );
urlConfigCheckboxes.innerHTML = urlConfigHtml;
addEvent( urlConfigCheckboxes, "change", function( event ) {
var params = {};
params[ event.target.name ] = event.target.checked ? true : undefined;
window.location = QUnit.url( params );
});
toolbar.appendChild( urlConfigCheckboxes );
if (numModules > 1) {
moduleFilter = document.createElement( 'span' );
moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
moduleFilter.innerHTML = moduleFilterHtml;
addEvent( moduleFilter, "change", function() {
var selectBox = moduleFilter.getElementsByTagName("select")[0],
selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
});
toolbar.appendChild(moduleFilter);
}
}
// `main` initialized at top of scope
@@ -970,9 +1072,9 @@ window.onerror = function ( error, filePath, linerNr ) {
}
QUnit.pushFailure( error, filePath + ":" + linerNr );
} else {
QUnit.test( "global failure", function() {
QUnit.test( "global failure", extend( function() {
QUnit.pushFailure( error, filePath + ":" + linerNr );
});
}, { validTest: validTest } ) );
}
return false;
}
@@ -1039,6 +1141,11 @@ function done() {
}
}
// scroll back to top to show results
if ( window.scrollTo ) {
window.scrollTo(0, 0);
}
runLoggingCallbacks( "done", QUnit, {
failed: config.stats.bad,
passed: passed,
@@ -1051,14 +1158,20 @@ function done() {
function validTest( test ) {
var include,
filter = config.filter && config.filter.toLowerCase(),
module = config.module,
module = config.module && config.module.toLowerCase(),
fullName = (test.module + ": " + test.testName).toLowerCase();
// Internally-generated tests are always valid
if ( test.callback && test.callback.validTest === validTest ) {
delete test.callback.validTest;
return true;
}
if ( config.testNumber ) {
return test.testNumber === config.testNumber;
}
if ( module && test.module !== module ) {
if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
return false;
}
@@ -1335,7 +1448,8 @@ QUnit.equiv = (function() {
a.global === b.global &&
// (gmi) ...
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline;
a.multiline === b.multiline &&
a.sticky === b.sticky;
},
// - skip when the property is a method of an instance (OOP)

View File

@@ -5,29 +5,29 @@
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore
(function(){var t=this,M=t._,p={},k=Array.prototype,q=Object.prototype,N=k.push,h=k.slice,O=k.unshift,m=q.toString,P=q.hasOwnProperty,A=k.forEach,B=k.map,C=k.reduce,D=k.reduceRight,E=k.filter,F=k.every,G=k.some,r=k.indexOf,H=k.lastIndexOf,q=Array.isArray,Q=Object.keys,u=Function.prototype.bind,b=function(a){return new l(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):t._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,c,
d){if(a!=null)if(A&&a.forEach===A)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(c.call(d,a[e],e,a)===p)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===p)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(B&&a.map===B)return a.map(c,b);j(a,function(a,g,i){e[e.length]=c.call(b,a,g,i)});return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(C&&a.reduce===C){e&&(c=b.bind(c,e));return f?a.reduce(c,
d):a.reduce(c)}j(a,function(a,b,h){if(f)d=c.call(e,d,a,b,h);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(D&&a.reduceRight===D){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;I(a,function(a,g,i){if(c.call(b,a,g,i)){e=
a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(E&&a.filter===E)return a.filter(c,b);j(a,function(a,g,i){c.call(b,a,g,i)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,i){c.call(b,a,g,i)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,d){c||(c=b.identity);var e=true;if(a==null)return e;if(F&&a.every===F)return a.every(c,d);j(a,function(a,b,i){if(!(e=e&&c.call(d,a,b,i)))return p});return!!e};var I=
b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(G&&a.some===G)return a.some(c,d);j(a,function(a,b,i){if(e||(e=c.call(d,a,b,i)))return p});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(r&&a.indexOf===r)return a.indexOf(c)!=-1;return b=I(a,function(a){return a===c})};b.invoke=function(a,c){var d=h.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c:a[c]).apply(a,d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};
b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,i){b=c?c.call(d,a,b,i):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,i){b=c?c.call(d,a,b,i):a;b<e.computed&&(e={value:a,computed:b})});
return e.value};b.shuffle=function(a){var c,b=0,e=[];j(a,function(a){c=Math.floor(Math.random()*++b);e[b-1]=e[c];e[c]=a});return e};b.sortBy=function(a,c,d){var e=J(a,c);return b.pluck(b.map(a,function(a,c,b){return{value:a,criteria:e.call(d,a,c,b)}}).sort(function(a,c){var b=a.criteria,d=c.criteria;return b===void 0?1:d===void 0?-1:b<d?-1:b>d?1:0}),"value")};var J=function(a,c){return b.isFunction(c)?c:function(a){return a[c]}},K=function(a,c,b){var e={},f=J(a,c);j(a,function(a,c){var h=f(a,c);b(e,
h,a)});return e};b.groupBy=function(a,c){return K(a,c,function(a,c,b){(a[c]||(a[c]=[])).push(b)})};b.countBy=function(a,c){return K(a,c,function(a,c){a[c]||(a[c]=0);a[c]++})};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var c=d(c),e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<c?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?h.call(a):b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=function(a){return a.length===+a.length?a.length:b.keys(a).length};b.first=
b.head=b.take=function(a,c,b){return c!=null&&!b?h.call(a,0,c):a[0]};b.initial=function(a,c,b){return h.call(a,0,a.length-(c==null||b?1:c))};b.last=function(a,c,b){return c!=null&&!b?h.call(a,Math.max(a.length-c,0)):a[a.length-1]};b.rest=b.tail=b.drop=function(a,c,b){return h.call(a,c==null||b?1:c)};b.compact=function(a){return b.filter(a,function(a){return!!a})};var s=function(a,c,d){j(a,function(a){b.isArray(a)?c?N.apply(d,a):s(a,c,d):d.push(a)});return d};b.flatten=function(a,c){return s(a,c,[])};
b.without=function(a){return b.difference(a,h.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,i){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[i])}return d},[]);return e};b.union=function(){return b.uniq(s(arguments,true,[]))};b.intersection=function(a){var c=h.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=s(h.call(arguments,
1),true,[]);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=h.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.object=function(a,c){for(var b={},e=0,f=a.length;e<f;e++)c?b[a[e]]=c[e]:b[a[e][0]]=a[e][1];return b};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(r&&a.indexOf===r)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=
function(a,c){if(a==null)return-1;if(H&&a.lastIndexOf===H)return a.lastIndexOf(c);for(var b=a.length;b--;)if(a[b]===c)return b;return-1};b.range=function(a,c,b){if(arguments.length<=1){c=a||0;a=0}for(var b=arguments[2]||1,e=Math.max(Math.ceil((c-a)/b),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+b}return g};var L=function(){};b.bind=function(a,c){var d,e;if(a.bind===u&&u)return u.apply(a,h.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=h.call(arguments,2);return d=function(){if(!(this instanceof
d))return a.apply(c,e.concat(h.call(arguments)));L.prototype=a.prototype;var b=new L,g=a.apply(b,e.concat(h.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=h.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,c){var b=h.call(arguments,2);return setTimeout(function(){return a.apply(null,
b)},c)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(h.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,i,h,j=b.debounce(function(){i=g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;i&&a.apply(d,e);j()},c));if(g)i=true;else{g=true;h=a.apply(d,e)}j();return h}};b.debounce=function(a,c,b){var e;return function(){var f=this,g=arguments,i=b&&!e;clearTimeout(e);e=setTimeout(function(){e=null;b||a.apply(f,g)},c);i&&a.apply(f,g)}};b.once=function(a){var b=
false,d;return function(){if(b)return d;b=true;d=a.apply(this,arguments);a=null;return d}};b.wrap=function(a,b){return function(){var d=[a].concat(h.call(arguments,0));return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=Q||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=
[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.pairs=function(a){return b.map(a,function(a,b){return[b,a]})};b.invert=function(a){return b.reduce(a,function(a,b,e){a[b]=e;return a},{})};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(h.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={},d=b.flatten(h.call(arguments,1));j(d,
function(b){b in a&&(c[b]=a[b])});return c};b.omit=function(a){var c={},d=b.flatten(h.call(arguments,1)),e;for(e in a)b.include(d,e)||(c[e]=a[e]);return c};b.defaults=function(a){j(h.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};var v=function(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=
c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=m.call(a);if(e!=m.call(c))return false;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;
for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){f=a.length;if(g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&v(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var i in a)if(b.has(a,i)){f++;if(!(g=b.has(c,i)&&v(a[i],c[i],d)))break}if(g){for(i in c)if(b.has(c,i)&&!f--)break;g=!f}}d.pop();return g};b.isEqual=function(a,b){return v(a,b,[])};b.isEmpty=function(a){if(a==null)return true;if(b.isArray(a)||
b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=q||function(a){return m.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};j("Arguments,Function,String,Number,Date,RegExp".split(","),function(a){b["is"+a]=function(b){return m.call(b)=="[object "+a+"]"}});b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFinite=function(a){return b.isNumber(a)&&
isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||m.call(a)=="[object Boolean]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return P.call(a,b)};b.noConflict=function(){t._=M;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.random=function(a,b){return a+(0|Math.random()*(b-a+1))};var n={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;",
"'":"&#x27;","/":"&#x2F;"}};n.unescape=b.invert(n.escape);var R={escape:RegExp("["+b.keys(n.escape).join("")+"]","g"),unescape:RegExp("("+b.keys(n.unescape).join("|")+")","g")};b.each(["escape","unescape"],function(a){b[a]=function(b){return b==null?"":(""+b).replace(R[a],function(b){return n[a][b]})}});b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){S(c,b[c]=a[c])})};var T=0;b.uniqueId=function(a){var b=
T++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var w=/.^/,o={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},x;for(x in o)o[o[x]]=x;var U=/\\|'|\r|\n|\t|\u2028|\u2029/g,V=/\\(\\|'|r|n|t|u2028|u2029)/g,y=function(a){return a.replace(V,function(a,b){return o[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(U,function(a){return"\\"+o[a]}).replace(d.escape||w,
function(a,b){return"'+\n((__t=("+y(b)+"))==null?'':_.escape(__t))+\n'"}).replace(d.interpolate||w,function(a,b){return"'+\n((__t=("+y(b)+"))==null?'':__t)+\n'"}).replace(d.evaluate||w,function(a,b){return"';\n"+y(b)+"\n__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");a="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{var e=new Function(d.variable||"obj","_",a)}catch(f){f.source=a;throw f;}if(c)return e(c,b);c=function(a){return e.call(this,
a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};b.chain=function(a){return b(a).chain()};var l=function(a){this._wrapped=a};b.prototype=l.prototype;var z=function(a,c){return c?b(a).chain():a},S=function(a,c){l.prototype[a]=function(){var a=h.call(arguments);O.call(a,this._wrapped);return z(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];l.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);
(a=="shift"||a=="splice")&&d.length===0&&delete d[0];return z(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];l.prototype[a]=function(){return z(b.apply(this._wrapped,arguments),this._chain)}});l.prototype.chain=function(){this._chain=true;return this};l.prototype.value=function(){return this._wrapped}}).call(this);
(function(){var s=this,K=s._,o={},k=Array.prototype,p=Object.prototype,L=k.push,h=k.slice,l=p.toString,M=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,N=Object.keys,t=Function.prototype.bind,b=function(a){if(a instanceof b)return a;if(!(this instanceof b))return new b(a);this._wrapped=a};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;
b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(c.call(d,a[e],e,a)===o)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===o)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.map===z)return a.map(c,b);j(a,function(a,g,i){e[e.length]=c.call(b,a,g,i)});return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(A&&
a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,h){if(f)d=c.call(e,d,a,b,h);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,
c,b){var e;G(a,function(a,g,i){if(c.call(b,a,g,i)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,i){c.call(b,a,g,i)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,i){c.call(b,a,g,i)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,d){c||(c=b.identity);var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,d);j(a,function(a,b,
i){if(!(e=e&&c.call(d,a,b,i)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,i){if(e||(e=c.call(d,a,b,i)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=h.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c:a[c]).apply(a,
d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,i){b=c?c.call(d,a,b,i):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,
function(a,b,i){b=c?c.call(d,a,b,i):a;b<e.computed&&(e={value:a,computed:b})});return e.value};b.shuffle=function(a){var c,b=0,e=[];j(a,function(a){c=Math.floor(Math.random()*++b);e[b-1]=e[c];e[c]=a});return e};b.sortBy=function(a,c,d){var e=H(a,c);return b.pluck(b.map(a,function(a,c,b){return{value:a,criteria:e.call(d,a,c,b)}}).sort(function(a,c){var b=a.criteria,d=c.criteria;return b===void 0?1:d===void 0?-1:b<d?-1:b>d?1:0}),"value")};var H=function(a,c){return b.isFunction(c)?c:function(a){return a[c]}},
I=function(a,c,b){var e={},f=H(a,c);j(a,function(a,c){var h=f(a,c);b(e,h,a)});return e};b.groupBy=function(a,c){return I(a,c,function(a,c,b){(a[c]||(a[c]=[])).push(b)})};b.countBy=function(a,c){return I(a,c,function(a,c){a[c]||(a[c]=0);a[c]++})};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var c=d(c),e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<c?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?h.call(a):b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=
function(a){return a.length===+a.length?a.length:b.keys(a).length};b.first=b.head=b.take=function(a,c,b){return c!=null&&!b?h.call(a,0,c):a[0]};b.initial=function(a,c,b){return h.call(a,0,a.length-(c==null||b?1:c))};b.last=function(a,c,b){return c!=null&&!b?h.call(a,Math.max(a.length-c,0)):a[a.length-1]};b.rest=b.tail=b.drop=function(a,c,b){return h.call(a,c==null||b?1:c)};b.compact=function(a){return b.filter(a,function(a){return!!a})};var r=function(a,c,d){j(a,function(a){b.isArray(a)?c?L.apply(d,
a):r(a,c,d):d.push(a)});return d};b.flatten=function(a,b){return r(a,b,[])};b.without=function(a){return b.difference(a,h.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,i){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[i])}return d},[]);return e};b.union=function(){return b.uniq(r(arguments,true,[]))};b.intersection=function(a){var c=h.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,
a)>=0})})};b.difference=function(a){var c=r(h.call(arguments,1),true,[]);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=h.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.object=function(a,b){for(var d={},e=0,f=a.length;e<f;e++)b?d[a[e]]=b[e]:d[a[e][0]]=a[e][1];return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(q&&a.indexOf===q)return a.indexOf(c);d=
0;for(e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(F&&a.lastIndexOf===F)return a.lastIndexOf(b);for(var d=a.length;d--;)if(a[d]===b)return d;return-1};b.range=function(a,b,d){if(arguments.length<=1){b=a||0;a=0}for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+d}return g};var J=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,h.call(arguments,1));if(!b.isFunction(a))throw new TypeError;
e=h.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(h.call(arguments)));J.prototype=a.prototype;var b=new J,g=a.apply(b,e.concat(h.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=h.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=
function(a,b){var d=h.call(arguments,2);return setTimeout(function(){return a.apply(null,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(h.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,i,h,j=b.debounce(function(){i=g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;i&&a.apply(d,e);j()},c));if(g)i=true;else{g=true;h=a.apply(d,e)}j();return h}};b.debounce=function(a,b,d){var e;return function(){var f=this,g=arguments,i=d&&!e;clearTimeout(e);
e=setTimeout(function(){e=null;d||a.apply(f,g)},b);i&&a.apply(f,g)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;d=a.apply(this,arguments);a=null;return d}};b.wrap=function(a,b){return function(){var d=[a].concat(h.call(arguments,0));return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};
b.keys=N||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.pairs=function(a){return b.map(a,function(a,b){return[b,a]})};b.invert=function(a){return b.reduce(a,function(a,b,e){a[b]=e;return a},{})};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(h.call(arguments,1),function(b){for(var d in b)a[d]=
b[d]});return a};b.pick=function(a){var c={},d=b.flatten(h.call(arguments,1));j(d,function(b){b in a&&(c[b]=a[b])});return c};b.omit=function(a){var c={},d=b.flatten(h.call(arguments,1)),e;for(e in a)b.include(d,e)||(c[e]=a[e]);return c};b.defaults=function(a){j(h.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};var u=function(a,c,d){if(a===c)return a!==
0||1/a==1/c;if(a==null||c==null)return a===c;if(a instanceof b)a=a._wrapped;if(c instanceof b)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==c.source&&a.global==c.global&&
a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){f=a.length;if(g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&u(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var i in a)if(b.has(a,i)){f++;if(!(g=b.has(c,i)&&u(a[i],c[i],d)))break}if(g){for(i in c)if(b.has(c,i)&&!f--)break;g=!f}}d.pop();
return g};b.isEqual=function(a,b){return u(a,b,[])};b.isEmpty=function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};j("Arguments,Function,String,Number,Date,RegExp".split(","),function(a){b["is"+a]=function(b){return l.call(b)=="[object "+a+"]"}});b.isArguments(arguments)||
(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return M.call(a,b)};b.noConflict=function(){s._=K;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.random=
function(a,b){return a+(0|Math.random()*(b-a+1))};var m={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;"}};m.unescape=b.invert(m.escape);var O={escape:RegExp("["+b.keys(m.escape).join("")+"]","g"),unescape:RegExp("("+b.keys(m.unescape).join("|")+")","g")};b.each(["escape","unescape"],function(a){b[a]=function(b){return b==null?"":(""+b).replace(O[a],function(b){return m[a][b]})}});b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):
d};b.mixin=function(a){j(b.functions(a),function(c){var d=b[c]=a[c];b.prototype[c]=function(){var a=h.call(arguments);a.unshift(this._wrapped);a=d.apply(b,a);return this._chain?b(a).chain():a}})};var P=0;b.uniqueId=function(a){var b=P++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var v=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},w;for(w in n)n[n[w]]=w;var Q=/\\|'|\r|\n|\t|\u2028|\u2029/g,
R=/\\(\\|'|r|n|t|u2028|u2029)/g,x=function(a){return a.replace(R,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults({},d,b.templateSettings);a="__p+='"+a.replace(Q,function(a){return"\\"+n[a]}).replace(d.escape||v,function(a,b){return"'+\n((__t=("+x(b)+"))==null?'':_.escape(__t))+\n'"}).replace(d.interpolate||v,function(a,b){return"'+\n((__t=("+x(b)+"))==null?'':__t)+\n'"}).replace(d.evaluate||v,function(a,b){return"';\n"+x(b)+"\n__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+
a+"}\n");a="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{var e=new Function(d.variable||"obj","_",a)}catch(f){f.source=a;throw f;}if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};b.chain=function(a){return b(a).chain()};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var c=k[a];b.prototype[a]=function(){var d=this._wrapped;c.apply(d,
arguments);(a=="shift"||a=="splice")&&d.length===0&&delete d[0];return this._chain?b(d).chain():d}});j(["concat","join","slice"],function(a){var c=k[a];b.prototype[a]=function(){var a=c.apply(this._wrapped,arguments);return this._chain?b(a).chain():a}});b.extend(b.prototype,{chain:function(){this._chain=true;return this},value:function(){return this._wrapped}})}).call(this);

View File

@@ -47,7 +47,11 @@
nativeBind = FuncProto.bind;
// Create a safe reference to the Underscore object for use below.
var _ = function(obj) { return new wrapper(obj); };
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in
@@ -771,8 +775,8 @@
// A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b;
// Unwrap any wrapped objects.
if (a._chain) a = a._wrapped;
if (b._chain) b = b._wrapped;
if (a instanceof _) a = a._wrapped;
if (b instanceof _) b = b._wrapped;
// Invoke a custom `isEqual` method if one is provided.
if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
@@ -990,11 +994,15 @@
return _.isFunction(value) ? value.call(object) : value;
};
// Add your own custom functions to the Underscore object, ensuring that
// they're correctly added to the OOP wrapper as well.
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
each(_.functions(obj), function(name){
addToWrapper(name, _[name] = obj[name]);
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = slice.call(arguments);
args.unshift(this._wrapped);
return result.call(this, func.apply(_, args));
};
});
};
@@ -1047,7 +1055,7 @@
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) {
settings = _.defaults(settings || {}, _.templateSettings);
settings = _.defaults({}, settings, _.templateSettings);
// Compile the template source, taking care to escape characters that
// cannot be included in a string literal and then unescape them in code
@@ -1096,29 +1104,15 @@
return _(obj).chain();
};
// The OOP Wrapper
// OOP
// ---------------
// If Underscore is called as a function, it returns a wrapped object that
// can be used OO-style. This wrapper holds altered versions of all the
// underscore functions. Wrapped objects may be chained.
var wrapper = function(obj) { this._wrapped = obj; };
// Expose `wrapper.prototype` as `_.prototype`
_.prototype = wrapper.prototype;
// Helper function to continue chaining intermediate results.
var result = function(obj, chain) {
return chain ? _(obj).chain() : obj;
};
// A method to easily add functions to the OOP wrapper.
var addToWrapper = function(name, func) {
wrapper.prototype[name] = function() {
var args = slice.call(arguments);
unshift.call(args, this._wrapped);
return result(func.apply(_, args), this._chain);
};
var result = function(obj) {
return this._chain ? _(obj).chain() : obj;
};
// Add all of the Underscore functions to the wrapper object.
@@ -1127,31 +1121,35 @@
// Add all mutator Array functions to the wrapper.
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name];
wrapper.prototype[name] = function() {
_.prototype[name] = function() {
var obj = this._wrapped;
method.apply(obj, arguments);
if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
return result(obj, this._chain);
return result.call(this, obj);
};
});
// Add all accessor Array functions to the wrapper.
each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name];
wrapper.prototype[name] = function() {
return result(method.apply(this._wrapped, arguments), this._chain);
_.prototype[name] = function() {
return result.call(this, method.apply(this._wrapped, arguments));
};
});
// Start chaining a wrapped Underscore object.
wrapper.prototype.chain = function() {
this._chain = true;
return this;
};
_.extend(_.prototype, {
// Extracts the result from a wrapped and chained object.
wrapper.prototype.value = function() {
return this._wrapped;
};
// Start chaining a wrapped Underscore object.
chain: function() {
this._chain = true;
return this;
},
// Extracts the result from a wrapped and chained object.
value: function() {
return this._wrapped;
}
});
}).call(this);