Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
todomvc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Eugene Shen
todomvc
Commits
c45f1cc6
Commit
c45f1cc6
authored
Feb 17, 2014
by
Sindre Sorhus
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #853 from appleboy/gh-pages
upgrade backbone to 1.1.1 and underscore to 1.6.0
parents
55c44717
f57e0b77
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
247 additions
and
152 deletions
+247
-152
architecture-examples/backbone/bower.json
architecture-examples/backbone/bower.json
+2
-2
architecture-examples/backbone/bower_components/backbone/backbone.js
...e-examples/backbone/bower_components/backbone/backbone.js
+95
-67
architecture-examples/backbone/bower_components/underscore/underscore.js
...amples/backbone/bower_components/underscore/underscore.js
+150
-83
No files found.
architecture-examples/backbone/bower.json
View file @
c45f1cc6
...
...
@@ -2,8 +2,8 @@
"name"
:
"todomvc-backbone"
,
"version"
:
"0.0.0"
,
"dependencies"
:
{
"backbone"
:
"~1.1.
0
"
,
"underscore"
:
"~1.
5
.0"
,
"backbone"
:
"~1.1.
1
"
,
"underscore"
:
"~1.
6
.0"
,
"jquery"
:
"~2.0.0"
,
"todomvc-common"
:
"~0.1.4"
,
"backbone.localStorage"
:
"~1.1.0"
...
...
architecture-examples/backbone/bower_components/backbone/backbone.js
View file @
c45f1cc6
// Backbone.js 1.1.
0
// Backbone.js 1.1.
1
// (c) 2010-2011 Jeremy Ashkenas, DocumentCloud Inc.
// (c) 2011-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// (c) 2010-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Backbone may be freely distributed under the MIT license.
// For all details and documentation:
// http://backbonejs.org
(
function
(){
(
function
(
root
,
factory
)
{
// Set up Backbone appropriately for the environment. Start with AMD.
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
define
([
'
underscore
'
,
'
jquery
'
,
'
exports
'
],
function
(
_
,
$
,
exports
)
{
// Export global even in AMD case in case this script is loaded with
// others that may still expect a global Backbone.
root
.
Backbone
=
factory
(
root
,
exports
,
_
,
$
);
});
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
}
else
if
(
typeof
exports
!==
'
undefined
'
)
{
var
_
=
require
(
'
underscore
'
),
$
;
try
{
$
=
require
(
'
jquery
'
);
}
catch
(
e
)
{}
factory
(
root
,
exports
,
_
,
$
);
// Finally, as a browser global.
}
else
{
root
.
Backbone
=
factory
(
root
,
{},
root
.
_
,
(
root
.
jQuery
||
root
.
Zepto
||
root
.
ender
||
root
.
$
));
}
}(
this
,
function
(
root
,
Backbone
,
_
,
$
)
{
// Initial Setup
// -------------
// Save a reference to the global object (`window` in the browser, `exports`
// on the server).
var
root
=
this
;
// Save the previous value of the `Backbone` variable, so that it can be
// restored later on, if `noConflict` is used.
var
previousBackbone
=
root
.
Backbone
;
...
...
@@ -25,25 +41,12 @@
var
slice
=
array
.
slice
;
var
splice
=
array
.
splice
;
// The top-level namespace. All public Backbone classes and modules will
// be attached to this. Exported for both the browser and the server.
var
Backbone
;
if
(
typeof
exports
!==
'
undefined
'
)
{
Backbone
=
exports
;
}
else
{
Backbone
=
root
.
Backbone
=
{};
}
// Current version of the library. Keep in sync with `package.json`.
Backbone
.
VERSION
=
'
1.1.0
'
;
// Require Underscore, if we're on the server, and it's not already present.
var
_
=
root
.
_
;
if
(
!
_
&&
(
typeof
require
!==
'
undefined
'
))
_
=
require
(
'
underscore
'
);
Backbone
.
VERSION
=
'
1.1.1
'
;
// For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
// the `$` variable.
Backbone
.
$
=
root
.
jQuery
||
root
.
Zepto
||
root
.
ender
||
root
.
$
;
Backbone
.
$
=
$
;
// Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
// to its previous owner. Returns a reference to this Backbone object.
...
...
@@ -109,7 +112,7 @@
var
retain
,
ev
,
events
,
names
,
i
,
l
,
j
,
k
;
if
(
!
this
.
_events
||
!
eventsApi
(
this
,
'
off
'
,
name
,
[
callback
,
context
]))
return
this
;
if
(
!
name
&&
!
callback
&&
!
context
)
{
this
.
_events
=
{}
;
this
.
_events
=
void
0
;
return
this
;
}
names
=
name
?
[
name
]
:
_
.
keys
(
this
.
_events
);
...
...
@@ -205,7 +208,7 @@
case
1
:
while
(
++
i
<
l
)
(
ev
=
events
[
i
]).
callback
.
call
(
ev
.
ctx
,
a1
);
return
;
case
2
:
while
(
++
i
<
l
)
(
ev
=
events
[
i
]).
callback
.
call
(
ev
.
ctx
,
a1
,
a2
);
return
;
case
3
:
while
(
++
i
<
l
)
(
ev
=
events
[
i
]).
callback
.
call
(
ev
.
ctx
,
a1
,
a2
,
a3
);
return
;
default
:
while
(
++
i
<
l
)
(
ev
=
events
[
i
]).
callback
.
apply
(
ev
.
ctx
,
args
);
default
:
while
(
++
i
<
l
)
(
ev
=
events
[
i
]).
callback
.
apply
(
ev
.
ctx
,
args
);
return
;
}
};
...
...
@@ -350,7 +353,7 @@
// Trigger all relevant attribute changes.
if
(
!
silent
)
{
if
(
changes
.
length
)
this
.
_pending
=
true
;
if
(
changes
.
length
)
this
.
_pending
=
options
;
for
(
var
i
=
0
,
l
=
changes
.
length
;
i
<
l
;
i
++
)
{
this
.
trigger
(
'
change:
'
+
changes
[
i
],
this
,
current
[
changes
[
i
]],
options
);
}
...
...
@@ -361,6 +364,7 @@
if
(
changing
)
return
this
;
if
(
!
silent
)
{
while
(
this
.
_pending
)
{
options
=
this
.
_pending
;
this
.
_pending
=
false
;
this
.
trigger
(
'
change
'
,
this
,
options
);
}
...
...
@@ -528,9 +532,12 @@
// using Backbone's restful methods, override this to change the endpoint
// that will be called.
url
:
function
()
{
var
base
=
_
.
result
(
this
,
'
urlRoot
'
)
||
_
.
result
(
this
.
collection
,
'
url
'
)
||
urlError
();
var
base
=
_
.
result
(
this
,
'
urlRoot
'
)
||
_
.
result
(
this
.
collection
,
'
url
'
)
||
urlError
();
if
(
this
.
isNew
())
return
base
;
return
base
+
(
base
.
charAt
(
base
.
length
-
1
)
===
'
/
'
?
''
:
'
/
'
)
+
encodeURIComponent
(
this
.
id
);
return
base
.
replace
(
/
([^\/])
$/
,
'
$1
/
'
)
+
encodeURIComponent
(
this
.
id
);
},
// **parse** converts a response into the hash of attributes to be `set` on
...
...
@@ -546,7 +553,7 @@
// A model is new if it has never been saved to the server, and lacks an id.
isNew
:
function
()
{
return
this
.
id
==
null
;
return
!
this
.
has
(
this
.
idAttribute
)
;
},
// Check if the model is currently in a valid state.
...
...
@@ -650,7 +657,7 @@
options
.
index
=
index
;
model
.
trigger
(
'
remove
'
,
model
,
this
,
options
);
}
this
.
_removeReference
(
model
);
this
.
_removeReference
(
model
,
options
);
}
return
singular
?
models
[
0
]
:
models
;
},
...
...
@@ -676,11 +683,11 @@
// Turn bare objects into model references, and prevent invalid models
// from being added.
for
(
i
=
0
,
l
=
models
.
length
;
i
<
l
;
i
++
)
{
attrs
=
models
[
i
];
attrs
=
models
[
i
]
||
{}
;
if
(
attrs
instanceof
Model
)
{
id
=
model
=
attrs
;
}
else
{
id
=
attrs
[
targetModel
.
prototype
.
idAttribute
];
id
=
attrs
[
targetModel
.
prototype
.
idAttribute
||
'
id
'
];
}
// If a duplicate is found, prevent it from being added and
...
...
@@ -700,14 +707,13 @@
model
=
models
[
i
]
=
this
.
_prepareModel
(
attrs
,
options
);
if
(
!
model
)
continue
;
toAdd
.
push
(
model
);
// Listen to added models' events, and index models for lookup by
// `id` and by `cid`.
model
.
on
(
'
all
'
,
this
.
_onModelEvent
,
this
);
this
.
_byId
[
model
.
cid
]
=
model
;
if
(
model
.
id
!=
null
)
this
.
_byId
[
model
.
id
]
=
model
;
this
.
_addReference
(
model
,
options
);
}
if
(
order
)
order
.
push
(
existing
||
model
);
// Do not add multiple models with the same `id`.
model
=
existing
||
model
;
if
(
order
&&
(
model
.
isNew
()
||
!
modelMap
[
model
.
id
]))
order
.
push
(
model
);
modelMap
[
model
.
id
]
=
true
;
}
// Remove nonexistent models if appropriate.
...
...
@@ -745,7 +751,7 @@
}
if
(
sort
||
(
order
&&
order
.
length
))
this
.
trigger
(
'
sort
'
,
this
,
options
);
}
// Return the added (or merged) model (or models).
return
singular
?
models
[
0
]
:
models
;
},
...
...
@@ -757,7 +763,7 @@
reset
:
function
(
models
,
options
)
{
options
||
(
options
=
{});
for
(
var
i
=
0
,
l
=
this
.
models
.
length
;
i
<
l
;
i
++
)
{
this
.
_removeReference
(
this
.
models
[
i
]);
this
.
_removeReference
(
this
.
models
[
i
]
,
options
);
}
options
.
previousModels
=
this
.
models
;
this
.
_reset
();
...
...
@@ -798,7 +804,7 @@
// Get a model from the set by id.
get
:
function
(
obj
)
{
if
(
obj
==
null
)
return
void
0
;
return
this
.
_byId
[
obj
.
id
]
||
this
.
_byId
[
obj
.
cid
]
||
this
.
_byId
[
obj
];
return
this
.
_byId
[
obj
]
||
this
.
_byId
[
obj
.
id
]
||
this
.
_byId
[
obj
.
cid
];
},
// Get the model at the given index.
...
...
@@ -874,7 +880,7 @@
if
(
!
options
.
wait
)
this
.
add
(
model
,
options
);
var
collection
=
this
;
var
success
=
options
.
success
;
options
.
success
=
function
(
model
,
resp
,
options
)
{
options
.
success
=
function
(
model
,
resp
)
{
if
(
options
.
wait
)
collection
.
add
(
model
,
options
);
if
(
success
)
success
(
model
,
resp
,
options
);
};
...
...
@@ -904,10 +910,7 @@
// Prepare a hash of attributes (or other model) to be added to this
// collection.
_prepareModel
:
function
(
attrs
,
options
)
{
if
(
attrs
instanceof
Model
)
{
if
(
!
attrs
.
collection
)
attrs
.
collection
=
this
;
return
attrs
;
}
if
(
attrs
instanceof
Model
)
return
attrs
;
options
=
options
?
_
.
clone
(
options
)
:
{};
options
.
collection
=
this
;
var
model
=
new
this
.
model
(
attrs
,
options
);
...
...
@@ -916,8 +919,16 @@
return
false
;
},
// Internal method to create a model's ties to a collection.
_addReference
:
function
(
model
,
options
)
{
this
.
_byId
[
model
.
cid
]
=
model
;
if
(
model
.
id
!=
null
)
this
.
_byId
[
model
.
id
]
=
model
;
if
(
!
model
.
collection
)
model
.
collection
=
this
;
model
.
on
(
'
all
'
,
this
.
_onModelEvent
,
this
);
},
// Internal method to sever a model's ties to a collection.
_removeReference
:
function
(
model
)
{
_removeReference
:
function
(
model
,
options
)
{
if
(
this
===
model
.
collection
)
delete
model
.
collection
;
model
.
off
(
'
all
'
,
this
.
_onModelEvent
,
this
);
},
...
...
@@ -946,7 +957,7 @@
'
reject
'
,
'
every
'
,
'
all
'
,
'
some
'
,
'
any
'
,
'
include
'
,
'
contains
'
,
'
invoke
'
,
'
max
'
,
'
min
'
,
'
toArray
'
,
'
size
'
,
'
first
'
,
'
head
'
,
'
take
'
,
'
initial
'
,
'
rest
'
,
'
tail
'
,
'
drop
'
,
'
last
'
,
'
without
'
,
'
difference
'
,
'
indexOf
'
,
'
shuffle
'
,
'
lastIndexOf
'
,
'
isEmpty
'
,
'
chain
'
];
'
lastIndexOf
'
,
'
isEmpty
'
,
'
chain
'
,
'
sample
'
];
// Mix in each Underscore method as a proxy to `Collection#models`.
_
.
each
(
methods
,
function
(
method
)
{
...
...
@@ -958,7 +969,7 @@
});
// Underscore methods that take a property name as an argument.
var
attributeMethods
=
[
'
groupBy
'
,
'
countBy
'
,
'
sortBy
'
];
var
attributeMethods
=
[
'
groupBy
'
,
'
countBy
'
,
'
sortBy
'
,
'
indexBy
'
];
// Use attributes instead of properties.
_
.
each
(
attributeMethods
,
function
(
method
)
{
...
...
@@ -1180,7 +1191,9 @@
return
xhr
;
};
var
noXhrPatch
=
typeof
window
!==
'
undefined
'
&&
!!
window
.
ActiveXObject
&&
!
(
window
.
XMLHttpRequest
&&
(
new
XMLHttpRequest
).
dispatchEvent
);
var
noXhrPatch
=
typeof
window
!==
'
undefined
'
&&
!!
window
.
ActiveXObject
&&
!
(
window
.
XMLHttpRequest
&&
(
new
XMLHttpRequest
).
dispatchEvent
);
// Map from CRUD to HTTP for our default `Backbone.sync` implementation.
var
methodMap
=
{
...
...
@@ -1239,7 +1252,7 @@
var
router
=
this
;
Backbone
.
history
.
route
(
route
,
function
(
fragment
)
{
var
args
=
router
.
_extractParameters
(
route
,
fragment
);
callback
&&
callback
.
apply
(
router
,
args
);
router
.
execute
(
callback
,
args
);
router
.
trigger
.
apply
(
router
,
[
'
route:
'
+
name
].
concat
(
args
));
router
.
trigger
(
'
route
'
,
name
,
args
);
Backbone
.
history
.
trigger
(
'
route
'
,
router
,
name
,
args
);
...
...
@@ -1247,6 +1260,12 @@
return
this
;
},
// Execute a route handler with the provided parameters. This is an
// excellent place to do pre-route setup or post-route cleanup.
execute
:
function
(
callback
,
args
)
{
if
(
callback
)
callback
.
apply
(
this
,
args
);
},
// Simple proxy to `Backbone.history` to save a fragment into the history.
navigate
:
function
(
fragment
,
options
)
{
Backbone
.
history
.
navigate
(
fragment
,
options
);
...
...
@@ -1271,10 +1290,10 @@
route
=
route
.
replace
(
escapeRegExp
,
'
\\
$&
'
)
.
replace
(
optionalParam
,
'
(?:$1)?
'
)
.
replace
(
namedParam
,
function
(
match
,
optional
)
{
return
optional
?
match
:
'
([^
\
/
]+)
'
;
return
optional
?
match
:
'
([^
/?
]+)
'
;
})
.
replace
(
splatParam
,
'
(
.
*?)
'
);
return
new
RegExp
(
'
^
'
+
route
+
'
$
'
);
.
replace
(
splatParam
,
'
(
[^?]
*?)
'
);
return
new
RegExp
(
'
^
'
+
route
+
'
(?:
\\
?(.*))?
$
'
);
},
// Given a route, and a URL fragment that it matches, return the array of
...
...
@@ -1282,7 +1301,9 @@
// treated as `null` to normalize cross-browser behavior.
_extractParameters
:
function
(
route
,
fragment
)
{
var
params
=
route
.
exec
(
fragment
).
slice
(
1
);
return
_
.
map
(
params
,
function
(
param
)
{
return
_
.
map
(
params
,
function
(
param
,
i
)
{
// Don't decode the search params.
if
(
i
===
params
.
length
-
1
)
return
param
||
null
;
return
param
?
decodeURIComponent
(
param
)
:
null
;
});
}
...
...
@@ -1320,8 +1341,8 @@
// Cached regex for removing a trailing slash.
var
trailingSlash
=
/
\/
$/
;
// Cached regex for stripping urls of hash
and query
.
var
pathStripper
=
/
[
?#
]
.*$/
;
// Cached regex for stripping urls of hash.
var
pathStripper
=
/
#
.*$/
;
// Has the history handling already been started?
History
.
started
=
false
;
...
...
@@ -1333,6 +1354,11 @@
// twenty times a second.
interval
:
50
,
// Are we at the app root?
atRoot
:
function
()
{
return
this
.
location
.
pathname
.
replace
(
/
[^\/]
$/
,
'
$&/
'
)
===
this
.
root
;
},
// Gets the true hash value. Cannot use location.hash directly due to bug
// in Firefox where location.hash will always be decoded.
getHash
:
function
(
window
)
{
...
...
@@ -1345,7 +1371,7 @@
getFragment
:
function
(
fragment
,
forcePushState
)
{
if
(
fragment
==
null
)
{
if
(
this
.
_hasPushState
||
!
this
.
_wantsHashChange
||
forcePushState
)
{
fragment
=
this
.
location
.
pathname
;
fragment
=
decodeURI
(
this
.
location
.
pathname
+
this
.
location
.
search
)
;
var
root
=
this
.
root
.
replace
(
trailingSlash
,
''
);
if
(
!
fragment
.
indexOf
(
root
))
fragment
=
fragment
.
slice
(
root
.
length
);
}
else
{
...
...
@@ -1376,7 +1402,8 @@
this
.
root
=
(
'
/
'
+
this
.
root
+
'
/
'
).
replace
(
rootStripper
,
'
/
'
);
if
(
oldIE
&&
this
.
_wantsHashChange
)
{
this
.
iframe
=
Backbone
.
$
(
'
<iframe src="javascript:0" tabindex="-1" />
'
).
hide
().
appendTo
(
'
body
'
)[
0
].
contentWindow
;
var
frame
=
Backbone
.
$
(
'
<iframe src="javascript:0" tabindex="-1">
'
);
this
.
iframe
=
frame
.
hide
().
appendTo
(
'
body
'
)[
0
].
contentWindow
;
this
.
navigate
(
fragment
);
}
...
...
@@ -1394,7 +1421,6 @@
// opened by a non-pushState browser.
this
.
fragment
=
fragment
;
var
loc
=
this
.
location
;
var
atRoot
=
loc
.
pathname
.
replace
(
/
[^\/]
$/
,
'
$&/
'
)
===
this
.
root
;
// Transition from hashChange to pushState or vice versa if both are
// requested.
...
...
@@ -1402,17 +1428,17 @@
// 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
.
_hasPushState
&&
!
atRoot
)
{
if
(
!
this
.
_hasPushState
&&
!
this
.
atRoot
()
)
{
this
.
fragment
=
this
.
getFragment
(
null
,
true
);
this
.
location
.
replace
(
this
.
root
+
this
.
location
.
search
+
'
#
'
+
this
.
fragment
);
this
.
location
.
replace
(
this
.
root
+
'
#
'
+
this
.
fragment
);
// Return immediately as browser will do redirect to new url
return
true
;
// Or if we've started out with a hash-based route, but we're currently
// in a browser where it could be `pushState`-based instead...
}
else
if
(
this
.
_hasPushState
&&
atRoot
&&
loc
.
hash
)
{
}
else
if
(
this
.
_hasPushState
&&
this
.
atRoot
()
&&
loc
.
hash
)
{
this
.
fragment
=
this
.
getHash
().
replace
(
routeStripper
,
''
);
this
.
history
.
replaceState
({},
document
.
title
,
this
.
root
+
this
.
fragment
+
loc
.
search
);
this
.
history
.
replaceState
({},
document
.
title
,
this
.
root
+
this
.
fragment
);
}
}
...
...
@@ -1472,7 +1498,7 @@
var
url
=
this
.
root
+
(
fragment
=
this
.
getFragment
(
fragment
||
''
));
// Strip the
fragment of the query and
hash for matching.
// Strip the hash for matching.
fragment
=
fragment
.
replace
(
pathStripper
,
''
);
if
(
this
.
fragment
===
fragment
)
return
;
...
...
@@ -1578,4 +1604,6 @@
};
};
}).
call
(
this
);
return
Backbone
;
}));
architecture-examples/backbone/bower_components/underscore/underscore.js
View file @
c45f1cc6
// Underscore.js 1.
5.2
// Underscore.js 1.
6.0
// http://underscorejs.org
// (c) 2009-201
3
Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// (c) 2009-201
4
Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
(
function
()
{
...
...
@@ -65,7 +65,7 @@
}
// Current version.
_
.
VERSION
=
'
1.
5.2
'
;
_
.
VERSION
=
'
1.
6.0
'
;
// Collection Functions
// --------------------
...
...
@@ -74,7 +74,7 @@
// Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available.
var
each
=
_
.
each
=
_
.
forEach
=
function
(
obj
,
iterator
,
context
)
{
if
(
obj
==
null
)
return
;
if
(
obj
==
null
)
return
obj
;
if
(
nativeForEach
&&
obj
.
forEach
===
nativeForEach
)
{
obj
.
forEach
(
iterator
,
context
);
}
else
if
(
obj
.
length
===
+
obj
.
length
)
{
...
...
@@ -87,6 +87,7 @@
if
(
iterator
.
call
(
context
,
obj
[
keys
[
i
]],
keys
[
i
],
obj
)
===
breaker
)
return
;
}
}
return
obj
;
};
// Return the results of applying the iterator to each element.
...
...
@@ -152,10 +153,10 @@
};
// Return the first value which passes a truth test. Aliased as `detect`.
_
.
find
=
_
.
detect
=
function
(
obj
,
iterator
,
context
)
{
_
.
find
=
_
.
detect
=
function
(
obj
,
predicate
,
context
)
{
var
result
;
any
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
iterator
.
call
(
context
,
value
,
index
,
list
))
{
if
(
predicate
.
call
(
context
,
value
,
index
,
list
))
{
result
=
value
;
return
true
;
}
...
...
@@ -166,33 +167,33 @@
// Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`.
_
.
filter
=
_
.
select
=
function
(
obj
,
iterator
,
context
)
{
_
.
filter
=
_
.
select
=
function
(
obj
,
predicate
,
context
)
{
var
results
=
[];
if
(
obj
==
null
)
return
results
;
if
(
nativeFilter
&&
obj
.
filter
===
nativeFilter
)
return
obj
.
filter
(
iterator
,
context
);
if
(
nativeFilter
&&
obj
.
filter
===
nativeFilter
)
return
obj
.
filter
(
predicate
,
context
);
each
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
iterator
.
call
(
context
,
value
,
index
,
list
))
results
.
push
(
value
);
if
(
predicate
.
call
(
context
,
value
,
index
,
list
))
results
.
push
(
value
);
});
return
results
;
};
// Return all the elements for which a truth test fails.
_
.
reject
=
function
(
obj
,
iterator
,
context
)
{
_
.
reject
=
function
(
obj
,
predicate
,
context
)
{
return
_
.
filter
(
obj
,
function
(
value
,
index
,
list
)
{
return
!
iterator
.
call
(
context
,
value
,
index
,
list
);
return
!
predicate
.
call
(
context
,
value
,
index
,
list
);
},
context
);
};
// Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`.
_
.
every
=
_
.
all
=
function
(
obj
,
iterator
,
context
)
{
iterator
||
(
iterator
=
_
.
identity
);
_
.
every
=
_
.
all
=
function
(
obj
,
predicate
,
context
)
{
predicate
||
(
predicate
=
_
.
identity
);
var
result
=
true
;
if
(
obj
==
null
)
return
result
;
if
(
nativeEvery
&&
obj
.
every
===
nativeEvery
)
return
obj
.
every
(
iterator
,
context
);
if
(
nativeEvery
&&
obj
.
every
===
nativeEvery
)
return
obj
.
every
(
predicate
,
context
);
each
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
!
(
result
=
result
&&
iterator
.
call
(
context
,
value
,
index
,
list
)))
return
breaker
;
if
(
!
(
result
=
result
&&
predicate
.
call
(
context
,
value
,
index
,
list
)))
return
breaker
;
});
return
!!
result
;
};
...
...
@@ -200,13 +201,13 @@
// Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`.
var
any
=
_
.
some
=
_
.
any
=
function
(
obj
,
iterator
,
context
)
{
iterator
||
(
iterator
=
_
.
identity
);
var
any
=
_
.
some
=
_
.
any
=
function
(
obj
,
predicate
,
context
)
{
predicate
||
(
predicate
=
_
.
identity
);
var
result
=
false
;
if
(
obj
==
null
)
return
result
;
if
(
nativeSome
&&
obj
.
some
===
nativeSome
)
return
obj
.
some
(
iterator
,
context
);
if
(
nativeSome
&&
obj
.
some
===
nativeSome
)
return
obj
.
some
(
predicate
,
context
);
each
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
result
||
(
result
=
iterator
.
call
(
context
,
value
,
index
,
list
)))
return
breaker
;
if
(
result
||
(
result
=
predicate
.
call
(
context
,
value
,
index
,
list
)))
return
breaker
;
});
return
!!
result
;
};
...
...
@@ -232,25 +233,19 @@
// Convenience version of a common use case of `map`: fetching a property.
_
.
pluck
=
function
(
obj
,
key
)
{
return
_
.
map
(
obj
,
function
(
value
){
return
value
[
key
];
}
);
return
_
.
map
(
obj
,
_
.
property
(
key
)
);
};
// Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs.
_
.
where
=
function
(
obj
,
attrs
,
first
)
{
if
(
_
.
isEmpty
(
attrs
))
return
first
?
void
0
:
[];
return
_
[
first
?
'
find
'
:
'
filter
'
](
obj
,
function
(
value
)
{
for
(
var
key
in
attrs
)
{
if
(
attrs
[
key
]
!==
value
[
key
])
return
false
;
}
return
true
;
});
_
.
where
=
function
(
obj
,
attrs
)
{
return
_
.
filter
(
obj
,
_
.
matches
(
attrs
));
};
// Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs.
_
.
findWhere
=
function
(
obj
,
attrs
)
{
return
_
.
where
(
obj
,
attrs
,
true
);
return
_
.
find
(
obj
,
_
.
matches
(
attrs
)
);
};
// Return the maximum element or (element-based computation).
...
...
@@ -260,13 +255,15 @@
if
(
!
iterator
&&
_
.
isArray
(
obj
)
&&
obj
[
0
]
===
+
obj
[
0
]
&&
obj
.
length
<
65535
)
{
return
Math
.
max
.
apply
(
Math
,
obj
);
}
if
(
!
iterator
&&
_
.
isEmpty
(
obj
))
return
-
Infinity
;
var
result
=
{
computed
:
-
Infinity
,
value
:
-
Infinity
};
var
result
=
-
Infinity
,
lastComputed
=
-
Infinity
;
each
(
obj
,
function
(
value
,
index
,
list
)
{
var
computed
=
iterator
?
iterator
.
call
(
context
,
value
,
index
,
list
)
:
value
;
computed
>
result
.
computed
&&
(
result
=
{
value
:
value
,
computed
:
computed
});
if
(
computed
>
lastComputed
)
{
result
=
value
;
lastComputed
=
computed
;
}
});
return
result
.
value
;
return
result
;
};
// Return the minimum element (or element-based computation).
...
...
@@ -274,16 +271,18 @@
if
(
!
iterator
&&
_
.
isArray
(
obj
)
&&
obj
[
0
]
===
+
obj
[
0
]
&&
obj
.
length
<
65535
)
{
return
Math
.
min
.
apply
(
Math
,
obj
);
}
if
(
!
iterator
&&
_
.
isEmpty
(
obj
))
return
Infinity
;
var
result
=
{
computed
:
Infinity
,
value
:
Infinity
};
var
result
=
Infinity
,
lastComputed
=
Infinity
;
each
(
obj
,
function
(
value
,
index
,
list
)
{
var
computed
=
iterator
?
iterator
.
call
(
context
,
value
,
index
,
list
)
:
value
;
computed
<
result
.
computed
&&
(
result
=
{
value
:
value
,
computed
:
computed
});
if
(
computed
<
lastComputed
)
{
result
=
value
;
lastComputed
=
computed
;
}
});
return
result
.
value
;
return
result
;
};
// Shuffle an array, using the modern version of the
// Shuffle an array, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_
.
shuffle
=
function
(
obj
)
{
var
rand
;
...
...
@@ -297,11 +296,12 @@
return
shuffled
;
};
// Sample **n** random values from a
n array
.
// If **n** is not specified, returns a single random element
from the array
.
// Sample **n** random values from a
collection
.
// If **n** is not specified, returns a single random element.
// The internal `guard` argument allows it to work with `map`.
_
.
sample
=
function
(
obj
,
n
,
guard
)
{
if
(
arguments
.
length
<
2
||
guard
)
{
if
(
n
==
null
||
guard
)
{
if
(
obj
.
length
!==
+
obj
.
length
)
obj
=
_
.
values
(
obj
);
return
obj
[
_
.
random
(
obj
.
length
-
1
)];
}
return
_
.
shuffle
(
obj
).
slice
(
0
,
Math
.
max
(
0
,
n
));
...
...
@@ -309,12 +309,14 @@
// An internal function to generate lookup iterators.
var
lookupIterator
=
function
(
value
)
{
return
_
.
isFunction
(
value
)
?
value
:
function
(
obj
){
return
obj
[
value
];
};
if
(
value
==
null
)
return
_
.
identity
;
if
(
_
.
isFunction
(
value
))
return
value
;
return
_
.
property
(
value
);
};
// Sort the object's values by a criterion produced by an iterator.
_
.
sortBy
=
function
(
obj
,
value
,
context
)
{
var
iterator
=
lookupIterator
(
value
);
_
.
sortBy
=
function
(
obj
,
iterator
,
context
)
{
iterator
=
lookupIterator
(
iterator
);
return
_
.
pluck
(
_
.
map
(
obj
,
function
(
value
,
index
,
list
)
{
return
{
value
:
value
,
...
...
@@ -334,9 +336,9 @@
// An internal function used for aggregate "group by" operations.
var
group
=
function
(
behavior
)
{
return
function
(
obj
,
value
,
context
)
{
return
function
(
obj
,
iterator
,
context
)
{
var
result
=
{};
var
iterator
=
value
==
null
?
_
.
identity
:
lookupIterator
(
value
);
iterator
=
lookupIterator
(
iterator
);
each
(
obj
,
function
(
value
,
index
)
{
var
key
=
iterator
.
call
(
context
,
value
,
index
,
obj
);
behavior
(
result
,
key
,
value
);
...
...
@@ -348,7 +350,7 @@
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_
.
groupBy
=
group
(
function
(
result
,
key
,
value
)
{
(
_
.
has
(
result
,
key
)
?
result
[
key
]
:
(
result
[
key
]
=
[])).
push
(
value
)
;
_
.
has
(
result
,
key
)
?
result
[
key
].
push
(
value
)
:
result
[
key
]
=
[
value
]
;
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
...
...
@@ -367,7 +369,7 @@
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_
.
sortedIndex
=
function
(
array
,
obj
,
iterator
,
context
)
{
iterator
=
iterator
==
null
?
_
.
identity
:
lookupIterator
(
iterator
);
iterator
=
lookupIterator
(
iterator
);
var
value
=
iterator
.
call
(
context
,
obj
);
var
low
=
0
,
high
=
array
.
length
;
while
(
low
<
high
)
{
...
...
@@ -399,7 +401,9 @@
// allows it to work with `_.map`.
_
.
first
=
_
.
head
=
_
.
take
=
function
(
array
,
n
,
guard
)
{
if
(
array
==
null
)
return
void
0
;
return
(
n
==
null
)
||
guard
?
array
[
0
]
:
slice
.
call
(
array
,
0
,
n
);
if
((
n
==
null
)
||
guard
)
return
array
[
0
];
if
(
n
<
0
)
return
[];
return
slice
.
call
(
array
,
0
,
n
);
};
// Returns everything but the last entry of the array. Especially useful on
...
...
@@ -414,11 +418,8 @@
// values in the array. The **guard** check allows it to work with `_.map`.
_
.
last
=
function
(
array
,
n
,
guard
)
{
if
(
array
==
null
)
return
void
0
;
if
((
n
==
null
)
||
guard
)
{
return
array
[
array
.
length
-
1
];
}
else
{
return
slice
.
call
(
array
,
Math
.
max
(
array
.
length
-
n
,
0
));
}
if
((
n
==
null
)
||
guard
)
return
array
[
array
.
length
-
1
];
return
slice
.
call
(
array
,
Math
.
max
(
array
.
length
-
n
,
0
));
};
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
...
...
@@ -459,6 +460,16 @@
return
_
.
difference
(
array
,
slice
.
call
(
arguments
,
1
));
};
// Split an array into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_
.
partition
=
function
(
array
,
predicate
)
{
var
pass
=
[],
fail
=
[];
each
(
array
,
function
(
elem
)
{
(
predicate
(
elem
)
?
pass
:
fail
).
push
(
elem
);
});
return
[
pass
,
fail
];
};
// Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`.
...
...
@@ -492,7 +503,7 @@
var
rest
=
slice
.
call
(
arguments
,
1
);
return
_
.
filter
(
_
.
uniq
(
array
),
function
(
item
)
{
return
_
.
every
(
rest
,
function
(
other
)
{
return
_
.
indexOf
(
other
,
item
)
>=
0
;
return
_
.
contains
(
other
,
item
)
;
});
});
};
...
...
@@ -507,7 +518,7 @@
// Zip together multiple lists into a single array -- elements that share
// an index go together.
_
.
zip
=
function
()
{
var
length
=
_
.
max
(
_
.
pluck
(
arguments
,
"
length
"
).
concat
(
0
));
var
length
=
_
.
max
(
_
.
pluck
(
arguments
,
'
length
'
).
concat
(
0
));
var
results
=
new
Array
(
length
);
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
results
[
i
]
=
_
.
pluck
(
arguments
,
''
+
i
);
...
...
@@ -613,19 +624,27 @@
};
// Partially apply a function by creating a version that has had some of its
// arguments pre-filled, without changing its dynamic `this` context.
// arguments pre-filled, without changing its dynamic `this` context. _ acts
// as a placeholder, allowing any combination of arguments to be pre-filled.
_
.
partial
=
function
(
func
)
{
var
a
rgs
=
slice
.
call
(
arguments
,
1
);
var
boundA
rgs
=
slice
.
call
(
arguments
,
1
);
return
function
()
{
return
func
.
apply
(
this
,
args
.
concat
(
slice
.
call
(
arguments
)));
var
position
=
0
;
var
args
=
boundArgs
.
slice
();
for
(
var
i
=
0
,
length
=
args
.
length
;
i
<
length
;
i
++
)
{
if
(
args
[
i
]
===
_
)
args
[
i
]
=
arguments
[
position
++
];
}
while
(
position
<
arguments
.
length
)
args
.
push
(
arguments
[
position
++
]);
return
func
.
apply
(
this
,
args
);
};
};
// Bind all of an object's methods to that object. Useful for ensuring that
// all callbacks defined on an object belong to it.
// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
_
.
bindAll
=
function
(
obj
)
{
var
funcs
=
slice
.
call
(
arguments
,
1
);
if
(
funcs
.
length
===
0
)
throw
new
Error
(
"
bindAll must be passed function names
"
);
if
(
funcs
.
length
===
0
)
throw
new
Error
(
'
bindAll must be passed function names
'
);
each
(
funcs
,
function
(
f
)
{
obj
[
f
]
=
_
.
bind
(
obj
[
f
],
obj
);
});
return
obj
;
};
...
...
@@ -664,12 +683,13 @@
var
previous
=
0
;
options
||
(
options
=
{});
var
later
=
function
()
{
previous
=
options
.
leading
===
false
?
0
:
new
Date
;
previous
=
options
.
leading
===
false
?
0
:
_
.
now
()
;
timeout
=
null
;
result
=
func
.
apply
(
context
,
args
);
context
=
args
=
null
;
};
return
function
()
{
var
now
=
new
Date
;
var
now
=
_
.
now
()
;
if
(
!
previous
&&
options
.
leading
===
false
)
previous
=
now
;
var
remaining
=
wait
-
(
now
-
previous
);
context
=
this
;
...
...
@@ -679,6 +699,7 @@
timeout
=
null
;
previous
=
now
;
result
=
func
.
apply
(
context
,
args
);
context
=
args
=
null
;
}
else
if
(
!
timeout
&&
options
.
trailing
!==
false
)
{
timeout
=
setTimeout
(
later
,
remaining
);
}
...
...
@@ -692,24 +713,33 @@
// leading edge, instead of the trailing.
_
.
debounce
=
function
(
func
,
wait
,
immediate
)
{
var
timeout
,
args
,
context
,
timestamp
,
result
;
var
later
=
function
()
{
var
last
=
_
.
now
()
-
timestamp
;
if
(
last
<
wait
)
{
timeout
=
setTimeout
(
later
,
wait
-
last
);
}
else
{
timeout
=
null
;
if
(
!
immediate
)
{
result
=
func
.
apply
(
context
,
args
);
context
=
args
=
null
;
}
}
};
return
function
()
{
context
=
this
;
args
=
arguments
;
timestamp
=
new
Date
();
var
later
=
function
()
{
var
last
=
(
new
Date
())
-
timestamp
;
if
(
last
<
wait
)
{
timeout
=
setTimeout
(
later
,
wait
-
last
);
}
else
{
timeout
=
null
;
if
(
!
immediate
)
result
=
func
.
apply
(
context
,
args
);
}
};
timestamp
=
_
.
now
();
var
callNow
=
immediate
&&
!
timeout
;
if
(
!
timeout
)
{
timeout
=
setTimeout
(
later
,
wait
);
}
if
(
callNow
)
result
=
func
.
apply
(
context
,
args
);
if
(
callNow
)
{
result
=
func
.
apply
(
context
,
args
);
context
=
args
=
null
;
}
return
result
;
};
};
...
...
@@ -731,11 +761,7 @@
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
_
.
wrap
=
function
(
func
,
wrapper
)
{
return
function
()
{
var
args
=
[
func
];
push
.
apply
(
args
,
arguments
);
return
wrapper
.
apply
(
this
,
args
);
};
return
_
.
partial
(
wrapper
,
func
);
};
// Returns a function that is the composition of a list of functions, each
...
...
@@ -765,8 +791,9 @@
// Retrieve the names of an object's properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`
_
.
keys
=
nativeKeys
||
function
(
obj
)
{
if
(
obj
!==
Object
(
obj
))
throw
new
TypeError
(
'
Invalid object
'
);
_
.
keys
=
function
(
obj
)
{
if
(
!
_
.
isObject
(
obj
))
return
[];
if
(
nativeKeys
)
return
nativeKeys
(
obj
);
var
keys
=
[];
for
(
var
key
in
obj
)
if
(
_
.
has
(
obj
,
key
))
keys
.
push
(
key
);
return
keys
;
...
...
@@ -921,7 +948,8 @@
// from different frames are.
var
aCtor
=
a
.
constructor
,
bCtor
=
b
.
constructor
;
if
(
aCtor
!==
bCtor
&&
!
(
_
.
isFunction
(
aCtor
)
&&
(
aCtor
instanceof
aCtor
)
&&
_
.
isFunction
(
bCtor
)
&&
(
bCtor
instanceof
bCtor
)))
{
_
.
isFunction
(
bCtor
)
&&
(
bCtor
instanceof
bCtor
))
&&
(
'
constructor
'
in
a
&&
'
constructor
'
in
b
))
{
return
false
;
}
// Add the first object to the stack of traversed objects.
...
...
@@ -1061,6 +1089,30 @@
return
value
;
};
_
.
constant
=
function
(
value
)
{
return
function
()
{
return
value
;
};
};
_
.
property
=
function
(
key
)
{
return
function
(
obj
)
{
return
obj
[
key
];
};
};
// Returns a predicate for checking whether an object has a given set of `key:value` pairs.
_
.
matches
=
function
(
attrs
)
{
return
function
(
obj
)
{
if
(
obj
===
attrs
)
return
true
;
//avoid comparing an object to itself.
for
(
var
key
in
attrs
)
{
if
(
attrs
[
key
]
!==
obj
[
key
])
return
false
;
}
return
true
;
}
};
// Run a function **n** times.
_
.
times
=
function
(
n
,
iterator
,
context
)
{
var
accum
=
Array
(
Math
.
max
(
0
,
n
));
...
...
@@ -1077,6 +1129,9 @@
return
min
+
Math
.
floor
(
Math
.
random
()
*
(
max
-
min
+
1
));
};
// A (possibly faster) way to get the current timestamp as an integer.
_
.
now
=
Date
.
now
||
function
()
{
return
new
Date
().
getTime
();
};
// List of HTML entities for escaping.
var
entityMap
=
{
escape
:
{
...
...
@@ -1273,4 +1328,16 @@
});
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
define
(
'
underscore
'
,
[],
function
()
{
return
_
;
});
}
}).
call
(
this
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment