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
Sven Franck
todomvc
Commits
e80de6d1
Commit
e80de6d1
authored
Dec 14, 2014
by
Pascal Hartig
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Backbone: Update jQuery, localStorage plugin
parent
f6786e58
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
582 additions
and
9305 deletions
+582
-9305
examples/backbone/bower.json
examples/backbone/bower.json
+2
-2
examples/backbone/bower_components/backbone.localStorage/backbone.localStorage.js
...components/backbone.localStorage/backbone.localStorage.js
+83
-49
examples/backbone/bower_components/jquery/jquery.js
examples/backbone/bower_components/jquery/jquery.js
+0
-8829
examples/backbone/bower_components/underscore/underscore.js
examples/backbone/bower_components/underscore/underscore.js
+496
-424
examples/backbone/index.html
examples/backbone/index.html
+1
-1
No files found.
examples/backbone/bower.json
View file @
e80de6d1
...
...
@@ -3,8 +3,8 @@
"version"
:
"0.0.0"
,
"dependencies"
:
{
"backbone"
:
"~1.1.1"
,
"underscore"
:
"~1.
6
.0"
,
"jquery"
:
"~2.
0
.0"
,
"underscore"
:
"~1.
7
.0"
,
"jquery"
:
"~2.
1
.0"
,
"todomvc-common"
:
"~0.3.0"
,
"backbone.localStorage"
:
"~1.1.0"
}
...
...
examples/backbone/bower_components/backbone.localStorage/backbone.localStorage.js
View file @
e80de6d1
/**
* Backbone localStorage Adapter
* Version 1.1.
7
* Version 1.1.
14
*
* https://github.com/jeromegn/Backbone.localStorage
*/
(
function
(
root
,
factory
)
{
if
(
typeof
exports
===
'
object
'
&&
typeof
require
===
'
function
'
)
{
module
.
exports
=
factory
(
require
(
"
underscore
"
),
require
(
"
backbone
"
));
}
else
if
(
typeof
define
===
"
function
"
&&
define
.
amd
)
{
// AMD. Register as an anonymous module.
define
([
"
underscore
"
,
"
backbone
"
],
function
(
_
,
Backbone
)
{
// Use global variables if the locals are undefined.
return
factory
(
_
||
root
.
_
,
Backbone
||
root
.
Backbone
);
});
}
else
{
// RequireJS isn't being used. Assume underscore and backbone are loaded in <script> tags
factory
(
_
,
Backbone
);
}
}(
this
,
function
(
_
,
Backbone
)
{
if
(
typeof
exports
===
'
object
'
&&
typeof
require
===
'
function
'
)
{
module
.
exports
=
factory
(
require
(
"
backbone
"
));
}
else
if
(
typeof
define
===
"
function
"
&&
define
.
amd
)
{
// AMD. Register as an anonymous module.
define
([
"
backbone
"
],
function
(
Backbone
)
{
// Use global variables if the locals are undefined.
return
factory
(
Backbone
||
root
.
Backbone
);
});
}
else
{
factory
(
Backbone
);
}
}(
this
,
function
(
Backbone
)
{
// A simple module to replace `Backbone.sync` with *localStorage*-based
// persistence. Models are given GUIDS, and saved into a JSON object. Simple
// as that.
// Hold reference to Underscore.js and Backbone.js in the closure in order
// to make things work even if they are removed from the global namespace
// Generate four random hex digits.
function
S4
()
{
return
(((
1
+
Math
.
random
())
*
0x10000
)
|
0
).
toString
(
16
).
substring
(
1
);
...
...
@@ -35,19 +31,49 @@ function guid() {
return
(
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
());
};
function
isObject
(
item
)
{
return
item
===
Object
(
item
);
}
function
contains
(
array
,
item
)
{
var
i
=
array
.
length
;
while
(
i
--
)
if
(
array
[
i
]
===
item
)
return
true
;
return
false
;
}
function
extend
(
obj
,
props
)
{
for
(
var
key
in
props
)
obj
[
key
]
=
props
[
key
]
return
obj
;
}
function
result
(
object
,
property
)
{
if
(
object
==
null
)
return
void
0
;
var
value
=
object
[
property
];
return
(
typeof
value
===
'
function
'
)
?
object
[
property
]()
:
value
;
}
// Our Store is represented by a single JS object in *localStorage*. Create it
// with a meaningful name, like the name you'd give a table.
// window.Store is deprectated, use Backbone.LocalStorage instead
Backbone
.
LocalStorage
=
window
.
Store
=
function
(
name
)
{
Backbone
.
LocalStorage
=
window
.
Store
=
function
(
name
,
serializer
)
{
if
(
!
this
.
localStorage
)
{
throw
"
Backbone.localStorage: Environment does not support localStorage.
"
}
this
.
name
=
name
;
this
.
serializer
=
serializer
||
{
serialize
:
function
(
item
)
{
return
isObject
(
item
)
?
JSON
.
stringify
(
item
)
:
item
;
},
// fix for "illegal access" error on Android when JSON.parse is passed null
deserialize
:
function
(
data
)
{
return
data
&&
JSON
.
parse
(
data
);
}
};
var
store
=
this
.
localStorage
().
getItem
(
this
.
name
);
this
.
records
=
(
store
&&
store
.
split
(
"
,
"
))
||
[];
};
_
.
extend
(
Backbone
.
LocalStorage
.
prototype
,
{
extend
(
Backbone
.
LocalStorage
.
prototype
,
{
// Save the current state of the **Store** to *localStorage*.
save
:
function
()
{
...
...
@@ -57,11 +83,11 @@ _.extend(Backbone.LocalStorage.prototype, {
// Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
// have an id of it's own.
create
:
function
(
model
)
{
if
(
!
model
.
id
)
{
if
(
!
model
.
id
&&
model
.
id
!==
0
)
{
model
.
id
=
guid
();
model
.
set
(
model
.
idAttribute
,
model
.
id
);
}
this
.
localStorage
().
setItem
(
this
.
name
+
"
-
"
+
model
.
id
,
JSON
.
stringify
(
model
));
this
.
localStorage
().
setItem
(
this
.
_itemName
(
model
.
id
),
this
.
serializer
.
serialize
(
model
));
this
.
records
.
push
(
model
.
id
.
toString
());
this
.
save
();
return
this
.
find
(
model
);
...
...
@@ -69,36 +95,40 @@ _.extend(Backbone.LocalStorage.prototype, {
// Update a model by replacing its copy in `this.data`.
update
:
function
(
model
)
{
this
.
localStorage
().
setItem
(
this
.
name
+
"
-
"
+
model
.
id
,
JSON
.
stringify
(
model
));
if
(
!
_
.
include
(
this
.
records
,
model
.
id
.
toString
()))
this
.
records
.
push
(
model
.
id
.
toString
());
this
.
save
();
this
.
localStorage
().
setItem
(
this
.
_itemName
(
model
.
id
),
this
.
serializer
.
serialize
(
model
));
var
modelId
=
model
.
id
.
toString
();
if
(
!
contains
(
this
.
records
,
modelId
))
{
this
.
records
.
push
(
modelId
);
this
.
save
();
}
return
this
.
find
(
model
);
},
// Retrieve a model from `this.data` by id.
find
:
function
(
model
)
{
return
this
.
jsonData
(
this
.
localStorage
().
getItem
(
this
.
name
+
"
-
"
+
model
.
id
));
return
this
.
serializer
.
deserialize
(
this
.
localStorage
().
getItem
(
this
.
_itemName
(
model
.
id
)
));
},
// Return the array of all models currently in storage.
findAll
:
function
()
{
// Lodash removed _#chain in v1.0.0-rc.1
return
(
_
.
chain
||
_
)(
this
.
records
)
.
map
(
function
(
id
){
return
this
.
jsonData
(
this
.
localStorage
().
getItem
(
this
.
name
+
"
-
"
+
id
));
},
this
)
.
compact
()
.
value
()
;
var
result
=
[];
for
(
var
i
=
0
,
id
,
data
;
i
<
this
.
records
.
length
;
i
++
)
{
id
=
this
.
records
[
i
];
data
=
this
.
serializer
.
deserialize
(
this
.
localStorage
().
getItem
(
this
.
_itemName
(
id
)
));
if
(
data
!=
null
)
result
.
push
(
data
);
}
return
result
;
},
// Delete a model from `this.data`, returning it.
destroy
:
function
(
model
)
{
if
(
model
.
isNew
())
return
false
this
.
localStorage
().
removeItem
(
this
.
name
+
"
-
"
+
model
.
id
);
this
.
records
=
_
.
reject
(
this
.
records
,
function
(
id
){
return
id
===
model
.
id
.
toString
();
});
this
.
localStorage
().
removeItem
(
this
.
_itemName
(
model
.
id
));
var
modelId
=
model
.
id
.
toString
();
for
(
var
i
=
0
,
id
;
i
<
this
.
records
.
length
;
i
++
)
{
if
(
this
.
records
[
i
]
===
modelId
)
{
this
.
records
.
splice
(
i
,
1
);
}
}
this
.
save
();
return
model
;
},
...
...
@@ -107,11 +137,6 @@ _.extend(Backbone.LocalStorage.prototype, {
return
localStorage
;
},
// fix for "illegal access" error on Android when JSON.parse is passed null
jsonData
:
function
(
data
)
{
return
data
&&
JSON
.
parse
(
data
);
},
// Clear localStorage for specific collection.
_clear
:
function
()
{
var
local
=
this
.
localStorage
(),
...
...
@@ -120,11 +145,12 @@ _.extend(Backbone.LocalStorage.prototype, {
// Remove id-tracking item (e.g., "foo").
local
.
removeItem
(
this
.
name
);
// Lodash removed _#chain in v1.0.0-rc.1
// Match all data items (e.g., "foo-ID") and remove.
(
_
.
chain
||
_
)(
local
).
keys
()
.
filter
(
function
(
k
)
{
return
itemRe
.
test
(
k
);
})
.
each
(
function
(
k
)
{
local
.
removeItem
(
k
);
});
for
(
var
k
in
local
)
{
if
(
itemRe
.
test
(
k
))
{
local
.
removeItem
(
k
);
}
}
this
.
records
.
length
=
0
;
},
...
...
@@ -132,6 +158,10 @@ _.extend(Backbone.LocalStorage.prototype, {
// Size of localStorage.
_storageSize
:
function
()
{
return
this
.
localStorage
().
length
;
},
_itemName
:
function
(
id
)
{
return
this
.
name
+
"
-
"
+
id
;
}
});
...
...
@@ -140,9 +170,13 @@ _.extend(Backbone.LocalStorage.prototype, {
// *localStorage* property, which should be an instance of `Store`.
// window.Store.sync and Backbone.localSync is deprecated, use Backbone.LocalStorage.sync instead
Backbone
.
LocalStorage
.
sync
=
window
.
Store
.
sync
=
Backbone
.
localSync
=
function
(
method
,
model
,
options
)
{
var
store
=
model
.
localStorage
||
model
.
collection
.
localStorage
;
var
store
=
result
(
model
,
'
localStorage
'
)
||
result
(
model
.
collection
,
'
localStorage
'
)
;
var
resp
,
errorMessage
,
syncDfd
=
Backbone
.
$
.
Deferred
&&
Backbone
.
$
.
Deferred
();
//If $ is having Deferred - use it.
var
resp
,
errorMessage
;
//If $ is having Deferred - use it.
var
syncDfd
=
Backbone
.
$
?
(
Backbone
.
$
.
Deferred
&&
Backbone
.
$
.
Deferred
())
:
(
Backbone
.
Deferred
&&
Backbone
.
Deferred
());
try
{
...
...
examples/backbone/bower_components/jquery/jquery.js
deleted
100755 → 0
View file @
f6786e58
This source diff could not be displayed because it is too large. You can
view the blob
instead.
examples/backbone/bower_components/underscore/underscore.js
View file @
e80de6d1
// Underscore.js 1.
6
.0
// Underscore.js 1.
7
.0
// http://underscorejs.org
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
...
...
@@ -14,9 +14,6 @@
// Save the previous value of the `_` variable.
var
previousUnderscore
=
root
.
_
;
// Establish the object that gets returned to break out of a loop iteration.
var
breaker
=
{};
// Save bytes in the minified (but not gzipped) version:
var
ArrayProto
=
Array
.
prototype
,
ObjProto
=
Object
.
prototype
,
FuncProto
=
Function
.
prototype
;
...
...
@@ -31,15 +28,6 @@
// All **ECMAScript 5** native function implementations that we hope to use
// are declared here.
var
nativeForEach
=
ArrayProto
.
forEach
,
nativeMap
=
ArrayProto
.
map
,
nativeReduce
=
ArrayProto
.
reduce
,
nativeReduceRight
=
ArrayProto
.
reduceRight
,
nativeFilter
=
ArrayProto
.
filter
,
nativeEvery
=
ArrayProto
.
every
,
nativeSome
=
ArrayProto
.
some
,
nativeIndexOf
=
ArrayProto
.
indexOf
,
nativeLastIndexOf
=
ArrayProto
.
lastIndexOf
,
nativeIsArray
=
Array
.
isArray
,
nativeKeys
=
Object
.
keys
,
nativeBind
=
FuncProto
.
bind
;
...
...
@@ -53,8 +41,7 @@
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object via a string identifier,
// for Closure Compiler "advanced" mode.
// the browser, add `_` as a global object.
if
(
typeof
exports
!==
'
undefined
'
)
{
if
(
typeof
module
!==
'
undefined
'
&&
module
.
exports
)
{
exports
=
module
.
exports
=
_
;
...
...
@@ -65,98 +52,125 @@
}
// Current version.
_
.
VERSION
=
'
1.6.0
'
;
_
.
VERSION
=
'
1.7.0
'
;
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
var
createCallback
=
function
(
func
,
context
,
argCount
)
{
if
(
context
===
void
0
)
return
func
;
switch
(
argCount
==
null
?
3
:
argCount
)
{
case
1
:
return
function
(
value
)
{
return
func
.
call
(
context
,
value
);
};
case
2
:
return
function
(
value
,
other
)
{
return
func
.
call
(
context
,
value
,
other
);
};
case
3
:
return
function
(
value
,
index
,
collection
)
{
return
func
.
call
(
context
,
value
,
index
,
collection
);
};
case
4
:
return
function
(
accumulator
,
value
,
index
,
collection
)
{
return
func
.
call
(
context
,
accumulator
,
value
,
index
,
collection
);
};
}
return
function
()
{
return
func
.
apply
(
context
,
arguments
);
};
};
// A mostly-internal function to generate callbacks that can be applied
// to each element in a collection, returning the desired result — either
// identity, an arbitrary callback, a property matcher, or a property accessor.
_
.
iteratee
=
function
(
value
,
context
,
argCount
)
{
if
(
value
==
null
)
return
_
.
identity
;
if
(
_
.
isFunction
(
value
))
return
createCallback
(
value
,
context
,
argCount
);
if
(
_
.
isObject
(
value
))
return
_
.
matches
(
value
);
return
_
.
property
(
value
);
};
// Collection Functions
// --------------------
// The cornerstone, an `each` implementation, aka `forEach`.
// Handles
objects with the built-in `forEach`, arrays, and raw objects.
//
Delegates to **ECMAScript 5**'s native `forEach` if availabl
e.
var
each
=
_
.
each
=
_
.
forEach
=
function
(
obj
,
iterator
,
context
)
{
// Handles
raw objects in addition to array-likes. Treats all
//
sparse array-likes as if they were dens
e.
_
.
each
=
_
.
forEach
=
function
(
obj
,
iteratee
,
context
)
{
if
(
obj
==
null
)
return
obj
;
i
f
(
nativeForEach
&&
obj
.
forEach
===
nativeForEach
)
{
obj
.
forEach
(
iterator
,
context
)
;
}
else
if
(
obj
.
length
===
+
obj
.
length
)
{
for
(
var
i
=
0
,
length
=
obj
.
length
;
i
<
length
;
i
++
)
{
i
f
(
iterator
.
call
(
context
,
obj
[
i
],
i
,
obj
)
===
breaker
)
return
;
i
teratee
=
createCallback
(
iteratee
,
context
);
var
i
,
length
=
obj
.
length
;
if
(
length
===
+
length
)
{
for
(
i
=
0
;
i
<
length
;
i
++
)
{
i
teratee
(
obj
[
i
],
i
,
obj
)
;
}
}
else
{
var
keys
=
_
.
keys
(
obj
);
for
(
var
i
=
0
,
length
=
keys
.
length
;
i
<
length
;
i
++
)
{
i
f
(
iterator
.
call
(
context
,
obj
[
keys
[
i
]],
keys
[
i
],
obj
)
===
breaker
)
return
;
for
(
i
=
0
,
length
=
keys
.
length
;
i
<
length
;
i
++
)
{
i
teratee
(
obj
[
keys
[
i
]],
keys
[
i
],
obj
)
;
}
}
return
obj
;
};
// Return the results of applying the iterator to each element.
// Delegates to **ECMAScript 5**'s native `map` if available.
_
.
map
=
_
.
collect
=
function
(
obj
,
iterator
,
context
)
{
var
results
=
[];
if
(
obj
==
null
)
return
results
;
if
(
nativeMap
&&
obj
.
map
===
nativeMap
)
return
obj
.
map
(
iterator
,
context
);
each
(
obj
,
function
(
value
,
index
,
list
)
{
results
.
push
(
iterator
.
call
(
context
,
value
,
index
,
list
));
});
// Return the results of applying the iteratee to each element.
_
.
map
=
_
.
collect
=
function
(
obj
,
iteratee
,
context
)
{
if
(
obj
==
null
)
return
[];
iteratee
=
_
.
iteratee
(
iteratee
,
context
);
var
keys
=
obj
.
length
!==
+
obj
.
length
&&
_
.
keys
(
obj
),
length
=
(
keys
||
obj
).
length
,
results
=
Array
(
length
),
currentKey
;
for
(
var
index
=
0
;
index
<
length
;
index
++
)
{
currentKey
=
keys
?
keys
[
index
]
:
index
;
results
[
index
]
=
iteratee
(
obj
[
currentKey
],
currentKey
,
obj
);
}
return
results
;
};
var
reduceError
=
'
Reduce of empty array with no initial value
'
;
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
_
.
reduce
=
_
.
foldl
=
_
.
inject
=
function
(
obj
,
iterator
,
memo
,
context
)
{
var
initial
=
arguments
.
length
>
2
;
// or `foldl`.
_
.
reduce
=
_
.
foldl
=
_
.
inject
=
function
(
obj
,
iteratee
,
memo
,
context
)
{
if
(
obj
==
null
)
obj
=
[];
if
(
nativeReduce
&&
obj
.
reduce
===
nativeReduce
)
{
if
(
context
)
iterator
=
_
.
bind
(
iterator
,
context
);
return
initial
?
obj
.
reduce
(
iterator
,
memo
)
:
obj
.
reduce
(
iterator
);
iteratee
=
createCallback
(
iteratee
,
context
,
4
);
var
keys
=
obj
.
length
!==
+
obj
.
length
&&
_
.
keys
(
obj
),
length
=
(
keys
||
obj
).
length
,
index
=
0
,
currentKey
;
if
(
arguments
.
length
<
3
)
{
if
(
!
length
)
throw
new
TypeError
(
reduceError
);
memo
=
obj
[
keys
?
keys
[
index
++
]
:
index
++
];
}
for
(;
index
<
length
;
index
++
)
{
currentKey
=
keys
?
keys
[
index
]
:
index
;
memo
=
iteratee
(
memo
,
obj
[
currentKey
],
currentKey
,
obj
);
}
each
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
!
initial
)
{
memo
=
value
;
initial
=
true
;
}
else
{
memo
=
iterator
.
call
(
context
,
memo
,
value
,
index
,
list
);
}
});
if
(
!
initial
)
throw
new
TypeError
(
reduceError
);
return
memo
;
};
// The right-associative version of reduce, also known as `foldr`.
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
_
.
reduceRight
=
_
.
foldr
=
function
(
obj
,
iterator
,
memo
,
context
)
{
var
initial
=
arguments
.
length
>
2
;
_
.
reduceRight
=
_
.
foldr
=
function
(
obj
,
iteratee
,
memo
,
context
)
{
if
(
obj
==
null
)
obj
=
[];
if
(
nativeReduceRight
&&
obj
.
reduceRight
===
nativeReduceRight
)
{
if
(
context
)
iterator
=
_
.
bind
(
iterator
,
context
);
return
initial
?
obj
.
reduceRight
(
iterator
,
memo
)
:
obj
.
reduceRight
(
iterator
);
iteratee
=
createCallback
(
iteratee
,
context
,
4
);
var
keys
=
obj
.
length
!==
+
obj
.
length
&&
_
.
keys
(
obj
),
index
=
(
keys
||
obj
).
length
,
currentKey
;
if
(
arguments
.
length
<
3
)
{
if
(
!
index
)
throw
new
TypeError
(
reduceError
);
memo
=
obj
[
keys
?
keys
[
--
index
]
:
--
index
];
}
var
length
=
obj
.
length
;
if
(
length
!==
+
length
)
{
var
keys
=
_
.
keys
(
obj
);
length
=
keys
.
length
;
while
(
index
--
)
{
currentKey
=
keys
?
keys
[
index
]
:
index
;
memo
=
iteratee
(
memo
,
obj
[
currentKey
],
currentKey
,
obj
);
}
each
(
obj
,
function
(
value
,
index
,
list
)
{
index
=
keys
?
keys
[
--
length
]
:
--
length
;
if
(
!
initial
)
{
memo
=
obj
[
index
];
initial
=
true
;
}
else
{
memo
=
iterator
.
call
(
context
,
memo
,
obj
[
index
],
index
,
list
);
}
});
if
(
!
initial
)
throw
new
TypeError
(
reduceError
);
return
memo
;
};
// Return the first value which passes a truth test. Aliased as `detect`.
_
.
find
=
_
.
detect
=
function
(
obj
,
predicate
,
context
)
{
var
result
;
any
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
predicate
.
call
(
context
,
value
,
index
,
list
))
{
predicate
=
_
.
iteratee
(
predicate
,
context
);
_
.
some
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
predicate
(
value
,
index
,
list
))
{
result
=
value
;
return
true
;
}
...
...
@@ -165,61 +179,58 @@
};
// 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
,
predicate
,
context
)
{
var
results
=
[];
if
(
obj
==
null
)
return
results
;
if
(
nativeFilter
&&
obj
.
filter
===
nativeFilter
)
return
obj
.
filter
(
predicate
,
context
);
each
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
predicate
.
call
(
context
,
value
,
index
,
list
))
results
.
push
(
value
);
predicate
=
_
.
iteratee
(
predicate
,
context
);
_
.
each
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
predicate
(
value
,
index
,
list
))
results
.
push
(
value
);
});
return
results
;
};
// Return all the elements for which a truth test fails.
_
.
reject
=
function
(
obj
,
predicate
,
context
)
{
return
_
.
filter
(
obj
,
function
(
value
,
index
,
list
)
{
return
!
predicate
.
call
(
context
,
value
,
index
,
list
);
},
context
);
return
_
.
filter
(
obj
,
_
.
negate
(
_
.
iteratee
(
predicate
)),
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
,
predicate
,
context
)
{
predicate
||
(
predicate
=
_
.
identity
);
var
result
=
true
;
if
(
obj
==
null
)
return
result
;
if
(
nativeEvery
&&
obj
.
every
===
nativeEvery
)
return
obj
.
every
(
predicate
,
context
);
each
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
!
(
result
=
result
&&
predicate
.
call
(
context
,
value
,
index
,
list
)))
return
breaker
;
});
return
!!
result
;
if
(
obj
==
null
)
return
true
;
predicate
=
_
.
iteratee
(
predicate
,
context
);
var
keys
=
obj
.
length
!==
+
obj
.
length
&&
_
.
keys
(
obj
),
length
=
(
keys
||
obj
).
length
,
index
,
currentKey
;
for
(
index
=
0
;
index
<
length
;
index
++
)
{
currentKey
=
keys
?
keys
[
index
]
:
index
;
if
(
!
predicate
(
obj
[
currentKey
],
currentKey
,
obj
))
return
false
;
}
return
true
;
};
// 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
,
predicate
,
context
)
{
predicate
||
(
predicate
=
_
.
identity
);
var
result
=
false
;
if
(
obj
==
null
)
return
result
;
if
(
nativeSome
&&
obj
.
some
===
nativeSome
)
return
obj
.
some
(
predicate
,
context
);
each
(
obj
,
function
(
value
,
index
,
list
)
{
if
(
result
||
(
result
=
predicate
.
call
(
context
,
value
,
index
,
list
)))
return
breaker
;
});
return
!!
result
;
_
.
some
=
_
.
any
=
function
(
obj
,
predicate
,
context
)
{
if
(
obj
==
null
)
return
false
;
predicate
=
_
.
iteratee
(
predicate
,
context
);
var
keys
=
obj
.
length
!==
+
obj
.
length
&&
_
.
keys
(
obj
),
length
=
(
keys
||
obj
).
length
,
index
,
currentKey
;
for
(
index
=
0
;
index
<
length
;
index
++
)
{
currentKey
=
keys
?
keys
[
index
]
:
index
;
if
(
predicate
(
obj
[
currentKey
],
currentKey
,
obj
))
return
true
;
}
return
false
;
};
// Determine if the array or object contains a given value (using `===`).
// Aliased as `include`.
_
.
contains
=
_
.
include
=
function
(
obj
,
target
)
{
if
(
obj
==
null
)
return
false
;
if
(
nativeIndexOf
&&
obj
.
indexOf
===
nativeIndexOf
)
return
obj
.
indexOf
(
target
)
!=
-
1
;
return
any
(
obj
,
function
(
value
)
{
return
value
===
target
;
});
if
(
obj
.
length
!==
+
obj
.
length
)
obj
=
_
.
values
(
obj
);
return
_
.
indexOf
(
obj
,
target
)
>=
0
;
};
// Invoke a method (with arguments) on every item in a collection.
...
...
@@ -248,51 +259,67 @@
return
_
.
find
(
obj
,
_
.
matches
(
attrs
));
};
// Return the maximum element or (element-based computation).
// Can't optimize arrays of integers longer than 65,535 elements.
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
_
.
max
=
function
(
obj
,
iterator
,
context
)
{
if
(
!
iterator
&&
_
.
isArray
(
obj
)
&&
obj
[
0
]
===
+
obj
[
0
]
&&
obj
.
length
<
65535
)
{
return
Math
.
max
.
apply
(
Math
,
obj
);
}
var
result
=
-
Infinity
,
lastComputed
=
-
Infinity
;
each
(
obj
,
function
(
value
,
index
,
list
)
{
var
computed
=
iterator
?
iterator
.
call
(
context
,
value
,
index
,
list
)
:
value
;
if
(
computed
>
lastComputed
)
{
result
=
value
;
lastComputed
=
computed
;
// Return the maximum element (or element-based computation).
_
.
max
=
function
(
obj
,
iteratee
,
context
)
{
var
result
=
-
Infinity
,
lastComputed
=
-
Infinity
,
value
,
computed
;
if
(
iteratee
==
null
&&
obj
!=
null
)
{
obj
=
obj
.
length
===
+
obj
.
length
?
obj
:
_
.
values
(
obj
);
for
(
var
i
=
0
,
length
=
obj
.
length
;
i
<
length
;
i
++
)
{
value
=
obj
[
i
];
if
(
value
>
result
)
{
result
=
value
;
}
}
});
}
else
{
iteratee
=
_
.
iteratee
(
iteratee
,
context
);
_
.
each
(
obj
,
function
(
value
,
index
,
list
)
{
computed
=
iteratee
(
value
,
index
,
list
);
if
(
computed
>
lastComputed
||
computed
===
-
Infinity
&&
result
===
-
Infinity
)
{
result
=
value
;
lastComputed
=
computed
;
}
});
}
return
result
;
};
// Return the minimum element (or element-based computation).
_
.
min
=
function
(
obj
,
iterat
or
,
context
)
{
if
(
!
iterator
&&
_
.
isArray
(
obj
)
&&
obj
[
0
]
===
+
obj
[
0
]
&&
obj
.
length
<
65535
)
{
return
Math
.
min
.
apply
(
Math
,
obj
)
;
}
var
result
=
Infinity
,
lastComputed
=
Infinity
;
each
(
obj
,
function
(
value
,
index
,
list
)
{
var
computed
=
iterator
?
iterator
.
call
(
context
,
value
,
index
,
list
)
:
value
;
if
(
computed
<
lastComputed
)
{
result
=
value
;
lastComputed
=
computed
;
_
.
min
=
function
(
obj
,
iterat
ee
,
context
)
{
var
result
=
Infinity
,
lastComputed
=
Infinity
,
value
,
computed
;
if
(
iteratee
==
null
&&
obj
!=
null
)
{
obj
=
obj
.
length
===
+
obj
.
length
?
obj
:
_
.
values
(
obj
)
;
for
(
var
i
=
0
,
length
=
obj
.
length
;
i
<
length
;
i
++
)
{
value
=
obj
[
i
]
;
if
(
value
<
result
)
{
result
=
value
;
}
}
});
}
else
{
iteratee
=
_
.
iteratee
(
iteratee
,
context
);
_
.
each
(
obj
,
function
(
value
,
index
,
list
)
{
computed
=
iteratee
(
value
,
index
,
list
);
if
(
computed
<
lastComputed
||
computed
===
Infinity
&&
result
===
Infinity
)
{
result
=
value
;
lastComputed
=
computed
;
}
});
}
return
result
;
};
// Shuffle a
n array
, using the modern version of the
// Shuffle a
collection
, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_
.
shuffle
=
function
(
obj
)
{
var
rand
;
var
index
=
0
;
var
shuffled
=
[]
;
each
(
obj
,
function
(
value
)
{
rand
=
_
.
random
(
index
++
);
shuffled
[
index
-
1
]
=
shuffled
[
rand
];
shuffled
[
rand
]
=
value
;
}
);
var
set
=
obj
&&
obj
.
length
===
+
obj
.
length
?
obj
:
_
.
values
(
obj
)
;
var
length
=
set
.
length
;
var
shuffled
=
Array
(
length
)
;
for
(
var
index
=
0
,
rand
;
index
<
length
;
index
++
)
{
rand
=
_
.
random
(
0
,
index
);
if
(
rand
!==
index
)
shuffled
[
index
]
=
shuffled
[
rand
];
shuffled
[
rand
]
=
set
[
index
]
;
}
return
shuffled
;
};
...
...
@@ -307,21 +334,14 @@
return
_
.
shuffle
(
obj
).
slice
(
0
,
Math
.
max
(
0
,
n
));
};
// An internal function to generate lookup iterators.
var
lookupIterator
=
function
(
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
,
iterator
,
context
)
{
iterator
=
lookupIterator
(
iterator
);
// Sort the object's values by a criterion produced by an iteratee.
_
.
sortBy
=
function
(
obj
,
iteratee
,
context
)
{
iteratee
=
_
.
iteratee
(
iteratee
,
context
);
return
_
.
pluck
(
_
.
map
(
obj
,
function
(
value
,
index
,
list
)
{
return
{
value
:
value
,
index
:
index
,
criteria
:
iterat
or
.
call
(
context
,
value
,
index
,
list
)
criteria
:
iterat
ee
(
value
,
index
,
list
)
};
}).
sort
(
function
(
left
,
right
)
{
var
a
=
left
.
criteria
;
...
...
@@ -336,12 +356,12 @@
// An internal function used for aggregate "group by" operations.
var
group
=
function
(
behavior
)
{
return
function
(
obj
,
iterat
or
,
context
)
{
return
function
(
obj
,
iterat
ee
,
context
)
{
var
result
=
{};
iterat
or
=
lookupIterator
(
iterator
);
each
(
obj
,
function
(
value
,
index
)
{
var
key
=
iterat
or
.
call
(
context
,
value
,
index
,
obj
);
behavior
(
result
,
key
,
value
);
iterat
ee
=
_
.
iteratee
(
iteratee
,
context
);
_
.
each
(
obj
,
function
(
value
,
index
)
{
var
key
=
iterat
ee
(
value
,
index
,
obj
);
behavior
(
result
,
value
,
key
);
});
return
result
;
};
...
...
@@ -349,32 +369,32 @@
// 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
].
push
(
value
)
:
result
[
key
]
=
[
value
];
_
.
groupBy
=
group
(
function
(
result
,
value
,
key
)
{
if
(
_
.
has
(
result
,
key
))
result
[
key
].
push
(
value
);
else
result
[
key
]
=
[
value
];
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique.
_
.
indexBy
=
group
(
function
(
result
,
key
,
value
)
{
_
.
indexBy
=
group
(
function
(
result
,
value
,
key
)
{
result
[
key
]
=
value
;
});
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
_
.
countBy
=
group
(
function
(
result
,
key
)
{
_
.
has
(
result
,
key
)
?
result
[
key
]
++
:
result
[
key
]
=
1
;
_
.
countBy
=
group
(
function
(
result
,
value
,
key
)
{
if
(
_
.
has
(
result
,
key
))
result
[
key
]
++
;
else
result
[
key
]
=
1
;
});
// 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
,
iterat
or
,
context
)
{
iterat
or
=
lookupIterator
(
iterator
);
var
value
=
iterat
or
.
call
(
context
,
obj
);
_
.
sortedIndex
=
function
(
array
,
obj
,
iterat
ee
,
context
)
{
iterat
ee
=
_
.
iteratee
(
iteratee
,
context
,
1
);
var
value
=
iterat
ee
(
obj
);
var
low
=
0
,
high
=
array
.
length
;
while
(
low
<
high
)
{
var
mid
=
(
low
+
high
)
>>>
1
;
i
terator
.
call
(
context
,
array
[
mid
])
<
value
?
low
=
mid
+
1
:
high
=
mid
;
var
mid
=
low
+
high
>>>
1
;
i
f
(
iteratee
(
array
[
mid
])
<
value
)
low
=
mid
+
1
;
else
high
=
mid
;
}
return
low
;
};
...
...
@@ -390,7 +410,18 @@
// Return the number of elements in an object.
_
.
size
=
function
(
obj
)
{
if
(
obj
==
null
)
return
0
;
return
(
obj
.
length
===
+
obj
.
length
)
?
obj
.
length
:
_
.
keys
(
obj
).
length
;
return
obj
.
length
===
+
obj
.
length
?
obj
.
length
:
_
.
keys
(
obj
).
length
;
};
// Split a collection into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_
.
partition
=
function
(
obj
,
predicate
,
context
)
{
predicate
=
_
.
iteratee
(
predicate
,
context
);
var
pass
=
[],
fail
=
[];
_
.
each
(
obj
,
function
(
value
,
key
,
obj
)
{
(
predicate
(
value
,
key
,
obj
)
?
pass
:
fail
).
push
(
value
);
});
return
[
pass
,
fail
];
};
// Array Functions
...
...
@@ -401,7 +432,7 @@
// allows it to work with `_.map`.
_
.
first
=
_
.
head
=
_
.
take
=
function
(
array
,
n
,
guard
)
{
if
(
array
==
null
)
return
void
0
;
if
(
(
n
==
null
)
||
guard
)
return
array
[
0
];
if
(
n
==
null
||
guard
)
return
array
[
0
];
if
(
n
<
0
)
return
[];
return
slice
.
call
(
array
,
0
,
n
);
};
...
...
@@ -411,14 +442,14 @@
// the array, excluding the last N. The **guard** check allows it to work with
// `_.map`.
_
.
initial
=
function
(
array
,
n
,
guard
)
{
return
slice
.
call
(
array
,
0
,
array
.
length
-
((
n
==
null
)
||
guard
?
1
:
n
));
return
slice
.
call
(
array
,
0
,
Math
.
max
(
0
,
array
.
length
-
(
n
==
null
||
guard
?
1
:
n
)
));
};
// Get the last element of an array. Passing **n** will return the last N
// 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
];
if
(
n
==
null
||
guard
)
return
array
[
array
.
length
-
1
];
return
slice
.
call
(
array
,
Math
.
max
(
array
.
length
-
n
,
0
));
};
...
...
@@ -427,7 +458,7 @@
// the rest N values in the array. The **guard**
// check allows it to work with `_.map`.
_
.
rest
=
_
.
tail
=
_
.
drop
=
function
(
array
,
n
,
guard
)
{
return
slice
.
call
(
array
,
(
n
==
null
)
||
guard
?
1
:
n
);
return
slice
.
call
(
array
,
n
==
null
||
guard
?
1
:
n
);
};
// Trim out all falsy values from an array.
...
...
@@ -436,23 +467,26 @@
};
// Internal implementation of a recursive `flatten` function.
var
flatten
=
function
(
input
,
shallow
,
output
)
{
var
flatten
=
function
(
input
,
shallow
,
strict
,
output
)
{
if
(
shallow
&&
_
.
every
(
input
,
_
.
isArray
))
{
return
concat
.
apply
(
output
,
input
);
}
each
(
input
,
function
(
value
)
{
if
(
_
.
isArray
(
value
)
||
_
.
isArguments
(
value
))
{
shallow
?
push
.
apply
(
output
,
value
)
:
flatten
(
value
,
shallow
,
output
);
for
(
var
i
=
0
,
length
=
input
.
length
;
i
<
length
;
i
++
)
{
var
value
=
input
[
i
];
if
(
!
_
.
isArray
(
value
)
&&
!
_
.
isArguments
(
value
))
{
if
(
!
strict
)
output
.
push
(
value
);
}
else
if
(
shallow
)
{
push
.
apply
(
output
,
value
);
}
else
{
output
.
push
(
value
);
flatten
(
value
,
shallow
,
strict
,
output
);
}
}
);
}
return
output
;
};
// Flatten out an array, either recursively (by default), or just one level.
_
.
flatten
=
function
(
array
,
shallow
)
{
return
flatten
(
array
,
shallow
,
[]);
return
flatten
(
array
,
shallow
,
false
,
[]);
};
// Return a version of the array that does not contain the specified value(s).
...
...
@@ -460,68 +494,77 @@
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`.
_
.
uniq
=
_
.
unique
=
function
(
array
,
isSorted
,
iterator
,
context
)
{
if
(
_
.
isFunction
(
isSorted
))
{
context
=
iterator
;
iterator
=
isSorted
;
_
.
uniq
=
_
.
unique
=
function
(
array
,
isSorted
,
iteratee
,
context
)
{
if
(
array
==
null
)
return
[];
if
(
!
_
.
isBoolean
(
isSorted
))
{
context
=
iteratee
;
iteratee
=
isSorted
;
isSorted
=
false
;
}
var
initial
=
iterator
?
_
.
map
(
array
,
iterator
,
context
)
:
array
;
var
result
s
=
[];
if
(
iteratee
!=
null
)
iteratee
=
_
.
iteratee
(
iteratee
,
context
)
;
var
result
=
[];
var
seen
=
[];
each
(
initial
,
function
(
value
,
index
)
{
if
(
isSorted
?
(
!
index
||
seen
[
seen
.
length
-
1
]
!==
value
)
:
!
_
.
contains
(
seen
,
value
))
{
seen
.
push
(
value
);
results
.
push
(
array
[
index
]);
for
(
var
i
=
0
,
length
=
array
.
length
;
i
<
length
;
i
++
)
{
var
value
=
array
[
i
];
if
(
isSorted
)
{
if
(
!
i
||
seen
!==
value
)
result
.
push
(
value
);
seen
=
value
;
}
else
if
(
iteratee
)
{
var
computed
=
iteratee
(
value
,
i
,
array
);
if
(
_
.
indexOf
(
seen
,
computed
)
<
0
)
{
seen
.
push
(
computed
);
result
.
push
(
value
);
}
}
else
if
(
_
.
indexOf
(
result
,
value
)
<
0
)
{
result
.
push
(
value
);
}
}
);
return
result
s
;
}
return
result
;
};
// Produce an array that contains the union: each distinct element from all of
// the passed-in arrays.
_
.
union
=
function
()
{
return
_
.
uniq
(
_
.
flatten
(
arguments
,
true
));
return
_
.
uniq
(
flatten
(
arguments
,
true
,
true
,
[]
));
};
// Produce an array that contains every item shared between all the
// passed-in arrays.
_
.
intersection
=
function
(
array
)
{
var
rest
=
slice
.
call
(
arguments
,
1
);
return
_
.
filter
(
_
.
uniq
(
array
),
function
(
item
)
{
return
_
.
every
(
rest
,
function
(
other
)
{
return
_
.
contains
(
other
,
item
);
});
});
if
(
array
==
null
)
return
[];
var
result
=
[];
var
argsLength
=
arguments
.
length
;
for
(
var
i
=
0
,
length
=
array
.
length
;
i
<
length
;
i
++
)
{
var
item
=
array
[
i
];
if
(
_
.
contains
(
result
,
item
))
continue
;
for
(
var
j
=
1
;
j
<
argsLength
;
j
++
)
{
if
(
!
_
.
contains
(
arguments
[
j
],
item
))
break
;
}
if
(
j
===
argsLength
)
result
.
push
(
item
);
}
return
result
;
};
// Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain.
_
.
difference
=
function
(
array
)
{
var
rest
=
concat
.
apply
(
ArrayProto
,
slice
.
call
(
arguments
,
1
));
return
_
.
filter
(
array
,
function
(
value
){
return
!
_
.
contains
(
rest
,
value
);
});
var
rest
=
flatten
(
slice
.
call
(
arguments
,
1
),
true
,
true
,
[]);
return
_
.
filter
(
array
,
function
(
value
){
return
!
_
.
contains
(
rest
,
value
);
});
};
// 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
results
=
new
Array
(
length
);
_
.
zip
=
function
(
array
)
{
if
(
array
==
null
)
return
[];
var
length
=
_
.
max
(
arguments
,
'
length
'
).
length
;
var
results
=
Array
(
length
);
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
results
[
i
]
=
_
.
pluck
(
arguments
,
''
+
i
);
results
[
i
]
=
_
.
pluck
(
arguments
,
i
);
}
return
results
;
};
...
...
@@ -542,10 +585,8 @@
return
result
;
};
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
// we need this function. Return the position of the first occurrence of an
// item in an array, or -1 if the item is not included in the array.
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
// Return the position of the first occurrence of an item in an array,
// or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
_
.
indexOf
=
function
(
array
,
item
,
isSorted
)
{
...
...
@@ -553,26 +594,23 @@
var
i
=
0
,
length
=
array
.
length
;
if
(
isSorted
)
{
if
(
typeof
isSorted
==
'
number
'
)
{
i
=
(
isSorted
<
0
?
Math
.
max
(
0
,
length
+
isSorted
)
:
isSorted
)
;
i
=
isSorted
<
0
?
Math
.
max
(
0
,
length
+
isSorted
)
:
isSorted
;
}
else
{
i
=
_
.
sortedIndex
(
array
,
item
);
return
array
[
i
]
===
item
?
i
:
-
1
;
}
}
if
(
nativeIndexOf
&&
array
.
indexOf
===
nativeIndexOf
)
return
array
.
indexOf
(
item
,
isSorted
);
for
(;
i
<
length
;
i
++
)
if
(
array
[
i
]
===
item
)
return
i
;
return
-
1
;
};
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
_
.
lastIndexOf
=
function
(
array
,
item
,
from
)
{
if
(
array
==
null
)
return
-
1
;
var
hasIndex
=
from
!=
null
;
if
(
nativeLastIndexOf
&&
array
.
lastIndexOf
===
nativeLastIndexOf
)
{
return
hasIndex
?
array
.
lastIndexOf
(
item
,
from
)
:
array
.
lastIndexOf
(
item
);
var
idx
=
array
.
length
;
if
(
typeof
from
==
'
number
'
)
{
idx
=
from
<
0
?
idx
+
from
+
1
:
Math
.
min
(
idx
,
from
+
1
);
}
var
i
=
(
hasIndex
?
from
:
array
.
length
);
while
(
i
--
)
if
(
array
[
i
]
===
item
)
return
i
;
while
(
--
idx
>=
0
)
if
(
array
[
idx
]
===
item
)
return
idx
;
return
-
1
;
};
...
...
@@ -584,15 +622,13 @@
stop
=
start
||
0
;
start
=
0
;
}
step
=
arguments
[
2
]
||
1
;
step
=
step
||
1
;
var
length
=
Math
.
max
(
Math
.
ceil
((
stop
-
start
)
/
step
),
0
);
var
idx
=
0
;
var
range
=
new
Array
(
length
);
var
range
=
Array
(
length
);
while
(
idx
<
length
)
{
range
[
idx
++
]
=
start
;
start
+=
step
;
for
(
var
idx
=
0
;
idx
<
length
;
idx
++
,
start
+=
step
)
{
range
[
idx
]
=
start
;
}
return
range
;
...
...
@@ -602,7 +638,7 @@
// ------------------
// Reusable constructor function for prototype setting.
var
c
tor
=
function
(){};
var
C
tor
=
function
(){};
// Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
...
...
@@ -610,17 +646,18 @@
_
.
bind
=
function
(
func
,
context
)
{
var
args
,
bound
;
if
(
nativeBind
&&
func
.
bind
===
nativeBind
)
return
nativeBind
.
apply
(
func
,
slice
.
call
(
arguments
,
1
));
if
(
!
_
.
isFunction
(
func
))
throw
new
TypeError
;
if
(
!
_
.
isFunction
(
func
))
throw
new
TypeError
(
'
Bind must be called on a function
'
)
;
args
=
slice
.
call
(
arguments
,
2
);
return
bound
=
function
()
{
bound
=
function
()
{
if
(
!
(
this
instanceof
bound
))
return
func
.
apply
(
context
,
args
.
concat
(
slice
.
call
(
arguments
)));
c
tor
.
prototype
=
func
.
prototype
;
var
self
=
new
c
tor
;
c
tor
.
prototype
=
null
;
C
tor
.
prototype
=
func
.
prototype
;
var
self
=
new
C
tor
;
C
tor
.
prototype
=
null
;
var
result
=
func
.
apply
(
self
,
args
.
concat
(
slice
.
call
(
arguments
)));
if
(
Object
(
result
)
===
result
)
return
result
;
if
(
_
.
isObject
(
result
)
)
return
result
;
return
self
;
};
return
bound
;
};
// Partially apply a function by creating a version that has had some of its
...
...
@@ -643,27 +680,34 @@
// 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
'
);
each
(
funcs
,
function
(
f
)
{
obj
[
f
]
=
_
.
bind
(
obj
[
f
],
obj
);
});
var
i
,
length
=
arguments
.
length
,
key
;
if
(
length
<=
1
)
throw
new
Error
(
'
bindAll must be passed function names
'
);
for
(
i
=
1
;
i
<
length
;
i
++
)
{
key
=
arguments
[
i
];
obj
[
key
]
=
_
.
bind
(
obj
[
key
],
obj
);
}
return
obj
;
};
// Memoize an expensive function by storing its results.
_
.
memoize
=
function
(
func
,
hasher
)
{
var
memo
=
{};
hasher
||
(
hasher
=
_
.
identity
)
;
return
function
()
{
var
key
=
hasher
.
apply
(
this
,
arguments
);
return
_
.
has
(
memo
,
key
)
?
memo
[
key
]
:
(
memo
[
key
]
=
func
.
apply
(
this
,
arguments
))
;
var
memo
ize
=
function
(
key
)
{
var
cache
=
memoize
.
cache
;
var
address
=
hasher
?
hasher
.
apply
(
this
,
arguments
)
:
key
;
if
(
!
_
.
has
(
cache
,
address
))
cache
[
address
]
=
func
.
apply
(
this
,
arguments
);
return
cache
[
address
]
;
};
memoize
.
cache
=
{};
return
memoize
;
};
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
_
.
delay
=
function
(
func
,
wait
)
{
var
args
=
slice
.
call
(
arguments
,
2
);
return
setTimeout
(
function
(){
return
func
.
apply
(
null
,
args
);
},
wait
);
return
setTimeout
(
function
(){
return
func
.
apply
(
null
,
args
);
},
wait
);
};
// Defers a function, scheduling it to run after the current call stack has
...
...
@@ -681,12 +725,12 @@
var
context
,
args
,
result
;
var
timeout
=
null
;
var
previous
=
0
;
options
||
(
options
=
{})
;
if
(
!
options
)
options
=
{}
;
var
later
=
function
()
{
previous
=
options
.
leading
===
false
?
0
:
_
.
now
();
timeout
=
null
;
result
=
func
.
apply
(
context
,
args
);
context
=
args
=
null
;
if
(
!
timeout
)
context
=
args
=
null
;
};
return
function
()
{
var
now
=
_
.
now
();
...
...
@@ -694,12 +738,12 @@
var
remaining
=
wait
-
(
now
-
previous
);
context
=
this
;
args
=
arguments
;
if
(
remaining
<=
0
)
{
if
(
remaining
<=
0
||
remaining
>
wait
)
{
clearTimeout
(
timeout
);
timeout
=
null
;
previous
=
now
;
result
=
func
.
apply
(
context
,
args
);
context
=
args
=
null
;
if
(
!
timeout
)
context
=
args
=
null
;
}
else
if
(
!
timeout
&&
options
.
trailing
!==
false
)
{
timeout
=
setTimeout
(
later
,
remaining
);
}
...
...
@@ -716,13 +760,14 @@
var
later
=
function
()
{
var
last
=
_
.
now
()
-
timestamp
;
if
(
last
<
wait
)
{
if
(
last
<
wait
&&
last
>
0
)
{
timeout
=
setTimeout
(
later
,
wait
-
last
);
}
else
{
timeout
=
null
;
if
(
!
immediate
)
{
result
=
func
.
apply
(
context
,
args
);
context
=
args
=
null
;
if
(
!
timeout
)
context
=
args
=
null
;
}
}
};
...
...
@@ -732,9 +777,7 @@
args
=
arguments
;
timestamp
=
_
.
now
();
var
callNow
=
immediate
&&
!
timeout
;
if
(
!
timeout
)
{
timeout
=
setTimeout
(
later
,
wait
);
}
if
(
!
timeout
)
timeout
=
setTimeout
(
later
,
wait
);
if
(
callNow
)
{
result
=
func
.
apply
(
context
,
args
);
context
=
args
=
null
;
...
...
@@ -744,19 +787,6 @@
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_
.
once
=
function
(
func
)
{
var
ran
=
false
,
memo
;
return
function
()
{
if
(
ran
)
return
memo
;
ran
=
true
;
memo
=
func
.
apply
(
this
,
arguments
);
func
=
null
;
return
memo
;
};
};
// Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
...
...
@@ -764,16 +794,23 @@
return
_
.
partial
(
wrapper
,
func
);
};
// Returns a negated version of the passed-in predicate.
_
.
negate
=
function
(
predicate
)
{
return
function
()
{
return
!
predicate
.
apply
(
this
,
arguments
);
};
};
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
_
.
compose
=
function
()
{
var
funcs
=
arguments
;
var
args
=
arguments
;
var
start
=
args
.
length
-
1
;
return
function
()
{
var
args
=
arguments
;
for
(
var
i
=
funcs
.
length
-
1
;
i
>=
0
;
i
--
)
{
args
=
[
funcs
[
i
].
apply
(
this
,
args
)];
}
return
args
[
0
];
var
i
=
start
;
var
result
=
args
[
start
].
apply
(
this
,
arguments
);
while
(
i
--
)
result
=
args
[
i
].
call
(
this
,
result
);
return
result
;
};
};
...
...
@@ -786,6 +823,23 @@
};
};
// Returns a function that will only be executed before being called N times.
_
.
before
=
function
(
times
,
func
)
{
var
memo
;
return
function
()
{
if
(
--
times
>
0
)
{
memo
=
func
.
apply
(
this
,
arguments
);
}
else
{
func
=
null
;
}
return
memo
;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_
.
once
=
_
.
partial
(
_
.
before
,
2
);
// Object Functions
// ----------------
...
...
@@ -803,7 +857,7 @@
_
.
values
=
function
(
obj
)
{
var
keys
=
_
.
keys
(
obj
);
var
length
=
keys
.
length
;
var
values
=
new
Array
(
length
);
var
values
=
Array
(
length
);
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
values
[
i
]
=
obj
[
keys
[
i
]];
}
...
...
@@ -814,7 +868,7 @@
_
.
pairs
=
function
(
obj
)
{
var
keys
=
_
.
keys
(
obj
);
var
length
=
keys
.
length
;
var
pairs
=
new
Array
(
length
);
var
pairs
=
Array
(
length
);
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
pairs
[
i
]
=
[
keys
[
i
],
obj
[
keys
[
i
]]];
}
...
...
@@ -843,45 +897,62 @@
// Extend a given object with all the properties in passed-in object(s).
_
.
extend
=
function
(
obj
)
{
each
(
slice
.
call
(
arguments
,
1
),
function
(
source
)
{
if
(
source
)
{
for
(
var
prop
in
source
)
{
obj
[
prop
]
=
source
[
prop
];
if
(
!
_
.
isObject
(
obj
))
return
obj
;
var
source
,
prop
;
for
(
var
i
=
1
,
length
=
arguments
.
length
;
i
<
length
;
i
++
)
{
source
=
arguments
[
i
];
for
(
prop
in
source
)
{
if
(
hasOwnProperty
.
call
(
source
,
prop
))
{
obj
[
prop
]
=
source
[
prop
];
}
}
}
);
}
return
obj
;
};
// Return a copy of the object only containing the whitelisted properties.
_
.
pick
=
function
(
obj
)
{
var
copy
=
{};
var
keys
=
concat
.
apply
(
ArrayProto
,
slice
.
call
(
arguments
,
1
));
each
(
keys
,
function
(
key
)
{
if
(
key
in
obj
)
copy
[
key
]
=
obj
[
key
];
});
return
copy
;
_
.
pick
=
function
(
obj
,
iteratee
,
context
)
{
var
result
=
{},
key
;
if
(
obj
==
null
)
return
result
;
if
(
_
.
isFunction
(
iteratee
))
{
iteratee
=
createCallback
(
iteratee
,
context
);
for
(
key
in
obj
)
{
var
value
=
obj
[
key
];
if
(
iteratee
(
value
,
key
,
obj
))
result
[
key
]
=
value
;
}
}
else
{
var
keys
=
concat
.
apply
([],
slice
.
call
(
arguments
,
1
));
obj
=
new
Object
(
obj
);
for
(
var
i
=
0
,
length
=
keys
.
length
;
i
<
length
;
i
++
)
{
key
=
keys
[
i
];
if
(
key
in
obj
)
result
[
key
]
=
obj
[
key
];
}
}
return
result
;
};
// Return a copy of the object without the blacklisted properties.
_
.
omit
=
function
(
obj
)
{
var
copy
=
{};
var
keys
=
concat
.
apply
(
ArrayProto
,
slice
.
call
(
arguments
,
1
));
for
(
var
key
in
obj
)
{
if
(
!
_
.
contains
(
keys
,
key
))
copy
[
key
]
=
obj
[
key
];
_
.
omit
=
function
(
obj
,
iteratee
,
context
)
{
if
(
_
.
isFunction
(
iteratee
))
{
iteratee
=
_
.
negate
(
iteratee
);
}
else
{
var
keys
=
_
.
map
(
concat
.
apply
([],
slice
.
call
(
arguments
,
1
)),
String
);
iteratee
=
function
(
value
,
key
)
{
return
!
_
.
contains
(
keys
,
key
);
};
}
return
copy
;
return
_
.
pick
(
obj
,
iteratee
,
context
)
;
};
// Fill in a given object with default properties.
_
.
defaults
=
function
(
obj
)
{
each
(
slice
.
call
(
arguments
,
1
),
function
(
source
)
{
if
(
source
)
{
for
(
var
prop
in
source
)
{
if
(
obj
[
prop
]
===
void
0
)
obj
[
prop
]
=
source
[
prop
];
}
if
(
!
_
.
isObject
(
obj
))
return
obj
;
for
(
var
i
=
1
,
length
=
arguments
.
length
;
i
<
length
;
i
++
)
{
var
source
=
arguments
[
i
];
for
(
var
prop
in
source
)
{
if
(
obj
[
prop
]
===
void
0
)
obj
[
prop
]
=
source
[
prop
];
}
}
);
}
return
obj
;
};
...
...
@@ -903,7 +974,7 @@
var
eq
=
function
(
a
,
b
,
aStack
,
bStack
)
{
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if
(
a
===
b
)
return
a
!==
0
||
1
/
a
==
1
/
b
;
if
(
a
===
b
)
return
a
!==
0
||
1
/
a
==
=
1
/
b
;
// A strict comparison is necessary because `null == undefined`.
if
(
a
==
null
||
b
==
null
)
return
a
===
b
;
// Unwrap any wrapped objects.
...
...
@@ -911,29 +982,27 @@
if
(
b
instanceof
_
)
b
=
b
.
_wrapped
;
// Compare `[[Class]]` names.
var
className
=
toString
.
call
(
a
);
if
(
className
!=
toString
.
call
(
b
))
return
false
;
if
(
className
!=
=
toString
.
call
(
b
))
return
false
;
switch
(
className
)
{
// Strings, numbers, dates, and booleans are compared by value.
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
case
'
[object RegExp]
'
:
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case
'
[object String]
'
:
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return
a
==
String
(
b
)
;
return
''
+
a
===
''
+
b
;
case
'
[object Number]
'
:
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
// other numeric values.
return
a
!=
+
a
?
b
!=
+
b
:
(
a
==
0
?
1
/
a
==
1
/
b
:
a
==
+
b
);
// `NaN`s are equivalent, but non-reflexive.
// Object(NaN) is equivalent to NaN
if
(
+
a
!==
+
a
)
return
+
b
!==
+
b
;
// An `egal` comparison is performed for other numeric values.
return
+
a
===
0
?
1
/
+
a
===
1
/
b
:
+
a
===
+
b
;
case
'
[object Date]
'
:
case
'
[object Boolean]
'
:
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent.
return
+
a
==
+
b
;
// RegExps are compared by their source patterns and flags.
case
'
[object RegExp]
'
:
return
a
.
source
==
b
.
source
&&
a
.
global
==
b
.
global
&&
a
.
multiline
==
b
.
multiline
&&
a
.
ignoreCase
==
b
.
ignoreCase
;
return
+
a
===
+
b
;
}
if
(
typeof
a
!=
'
object
'
||
typeof
b
!=
'
object
'
)
return
false
;
// Assume equality for cyclic structures. The algorithm for detecting cyclic
...
...
@@ -942,25 +1011,29 @@
while
(
length
--
)
{
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if
(
aStack
[
length
]
==
a
)
return
bStack
[
length
]
==
b
;
if
(
aStack
[
length
]
==
=
a
)
return
bStack
[
length
]
=
==
b
;
}
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var
aCtor
=
a
.
constructor
,
bCtor
=
b
.
constructor
;
if
(
aCtor
!==
bCtor
&&
!
(
_
.
isFunction
(
aCtor
)
&&
(
aCtor
instanceof
aCtor
)
&&
_
.
isFunction
(
bCtor
)
&&
(
bCtor
instanceof
bCtor
))
&&
(
'
constructor
'
in
a
&&
'
constructor
'
in
b
))
{
if
(
aCtor
!==
bCtor
&&
// Handle Object.create(x) cases
'
constructor
'
in
a
&&
'
constructor
'
in
b
&&
!
(
_
.
isFunction
(
aCtor
)
&&
aCtor
instanceof
aCtor
&&
_
.
isFunction
(
bCtor
)
&&
bCtor
instanceof
bCtor
)
)
{
return
false
;
}
// Add the first object to the stack of traversed objects.
aStack
.
push
(
a
);
bStack
.
push
(
b
);
var
size
=
0
,
result
=
true
;
var
size
,
result
;
// Recursively compare objects and arrays.
if
(
className
==
'
[object Array]
'
)
{
if
(
className
==
=
'
[object Array]
'
)
{
// Compare array lengths to determine if a deep comparison is necessary.
size
=
a
.
length
;
result
=
size
==
b
.
length
;
result
=
size
==
=
b
.
length
;
if
(
result
)
{
// Deep compare the contents, ignoring non-numeric properties.
while
(
size
--
)
{
...
...
@@ -969,20 +1042,16 @@
}
}
else
{
// Deep compare objects.
for
(
var
key
in
a
)
{
if
(
_
.
has
(
a
,
key
))
{
// Count the expected number of properties.
size
++
;
// Deep compare each member.
if
(
!
(
result
=
_
.
has
(
b
,
key
)
&&
eq
(
a
[
key
],
b
[
key
],
aStack
,
bStack
)))
break
;
}
}
// Ensure that both objects contain the same number of properties.
var
keys
=
_
.
keys
(
a
),
key
;
size
=
keys
.
length
;
// Ensure that both objects contain the same number of properties before comparing deep equality.
result
=
_
.
keys
(
b
).
length
===
size
;
if
(
result
)
{
for
(
key
in
b
)
{
if
(
_
.
has
(
b
,
key
)
&&
!
(
size
--
))
break
;
while
(
size
--
)
{
// Deep compare each member
key
=
keys
[
size
];
if
(
!
(
result
=
_
.
has
(
b
,
key
)
&&
eq
(
a
[
key
],
b
[
key
],
aStack
,
bStack
)))
break
;
}
result
=
!
size
;
}
}
// Remove the first object from the stack of traversed objects.
...
...
@@ -1000,7 +1069,7 @@
// An "empty" object has no enumerable own-properties.
_
.
isEmpty
=
function
(
obj
)
{
if
(
obj
==
null
)
return
true
;
if
(
_
.
isArray
(
obj
)
||
_
.
isString
(
obj
))
return
obj
.
length
===
0
;
if
(
_
.
isArray
(
obj
)
||
_
.
isString
(
obj
)
||
_
.
isArguments
(
obj
)
)
return
obj
.
length
===
0
;
for
(
var
key
in
obj
)
if
(
_
.
has
(
obj
,
key
))
return
false
;
return
true
;
};
...
...
@@ -1013,18 +1082,19 @@
// Is a given value an array?
// Delegates to ECMA5's native Array.isArray
_
.
isArray
=
nativeIsArray
||
function
(
obj
)
{
return
toString
.
call
(
obj
)
==
'
[object Array]
'
;
return
toString
.
call
(
obj
)
==
=
'
[object Array]
'
;
};
// Is a given variable an object?
_
.
isObject
=
function
(
obj
)
{
return
obj
===
Object
(
obj
);
var
type
=
typeof
obj
;
return
type
===
'
function
'
||
type
===
'
object
'
&&
!!
obj
;
};
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
each
([
'
Arguments
'
,
'
Function
'
,
'
String
'
,
'
Number
'
,
'
Date
'
,
'
RegExp
'
],
function
(
name
)
{
_
.
each
([
'
Arguments
'
,
'
Function
'
,
'
String
'
,
'
Number
'
,
'
Date
'
,
'
RegExp
'
],
function
(
name
)
{
_
[
'
is
'
+
name
]
=
function
(
obj
)
{
return
toString
.
call
(
obj
)
==
'
[object
'
+
name
+
'
]
'
;
return
toString
.
call
(
obj
)
==
=
'
[object
'
+
name
+
'
]
'
;
};
});
...
...
@@ -1032,14 +1102,14 @@
// there isn't any inspectable "Arguments" type.
if
(
!
_
.
isArguments
(
arguments
))
{
_
.
isArguments
=
function
(
obj
)
{
return
!!
(
obj
&&
_
.
has
(
obj
,
'
callee
'
)
);
return
_
.
has
(
obj
,
'
callee
'
);
};
}
// Optimize `isFunction` if appropriate.
if
(
typeof
(
/./
)
!==
'
function
'
)
{
// Optimize `isFunction` if appropriate.
Work around an IE 11 bug.
if
(
typeof
/./
!==
'
function
'
)
{
_
.
isFunction
=
function
(
obj
)
{
return
typeof
obj
==
=
'
function
'
;
return
typeof
obj
==
'
function
'
||
false
;
};
}
...
...
@@ -1050,12 +1120,12 @@
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
_
.
isNaN
=
function
(
obj
)
{
return
_
.
isNumber
(
obj
)
&&
obj
!=
+
obj
;
return
_
.
isNumber
(
obj
)
&&
obj
!=
=
+
obj
;
};
// Is a given value a boolean?
_
.
isBoolean
=
function
(
obj
)
{
return
obj
===
true
||
obj
===
false
||
toString
.
call
(
obj
)
==
'
[object Boolean]
'
;
return
obj
===
true
||
obj
===
false
||
toString
.
call
(
obj
)
==
=
'
[object Boolean]
'
;
};
// Is a given value equal to null?
...
...
@@ -1071,7 +1141,7 @@
// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
_
.
has
=
function
(
obj
,
key
)
{
return
hasOwnProperty
.
call
(
obj
,
key
);
return
obj
!=
null
&&
hasOwnProperty
.
call
(
obj
,
key
);
};
// Utility Functions
...
...
@@ -1084,17 +1154,19 @@
return
this
;
};
// Keep the identity function around for default iterat
or
s.
// Keep the identity function around for default iterat
ee
s.
_
.
identity
=
function
(
value
)
{
return
value
;
};
_
.
constant
=
function
(
value
)
{
return
function
()
{
return
function
()
{
return
value
;
};
};
_
.
noop
=
function
(){};
_
.
property
=
function
(
key
)
{
return
function
(
obj
)
{
return
obj
[
key
];
...
...
@@ -1103,20 +1175,23 @@
// Returns a predicate for checking whether an object has a given set of `key:value` pairs.
_
.
matches
=
function
(
attrs
)
{
var
pairs
=
_
.
pairs
(
attrs
),
length
=
pairs
.
length
;
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
;
if
(
obj
==
null
)
return
!
length
;
obj
=
new
Object
(
obj
);
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
var
pair
=
pairs
[
i
],
key
=
pair
[
0
];
if
(
pair
[
1
]
!==
obj
[
key
]
||
!
(
key
in
obj
))
return
false
;
}
return
true
;
}
}
;
};
// Run a function **n** times.
_
.
times
=
function
(
n
,
iterat
or
,
context
)
{
_
.
times
=
function
(
n
,
iterat
ee
,
context
)
{
var
accum
=
Array
(
Math
.
max
(
0
,
n
));
for
(
var
i
=
0
;
i
<
n
;
i
++
)
accum
[
i
]
=
iterator
.
call
(
context
,
i
);
iteratee
=
createCallback
(
iteratee
,
context
,
1
);
for
(
var
i
=
0
;
i
<
n
;
i
++
)
accum
[
i
]
=
iteratee
(
i
);
return
accum
;
};
...
...
@@ -1130,54 +1205,44 @@
};
// 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
:
{
'
&
'
:
'
&
'
,
'
<
'
:
'
<
'
,
'
>
'
:
'
>
'
,
'
"
'
:
'
"
'
,
"
'
"
:
'
'
'
}
_
.
now
=
Date
.
now
||
function
()
{
return
new
Date
().
getTime
();
};
entityMap
.
unescape
=
_
.
invert
(
entityMap
.
escape
);
// Regexes containing the keys and values listed immediately above.
var
entityRegexes
=
{
escape
:
new
RegExp
(
'
[
'
+
_
.
keys
(
entityMap
.
escape
).
join
(
''
)
+
'
]
'
,
'
g
'
),
unescape
:
new
RegExp
(
'
(
'
+
_
.
keys
(
entityMap
.
unescape
).
join
(
'
|
'
)
+
'
)
'
,
'
g
'
)
// List of HTML entities for escaping.
var
escapeMap
=
{
'
&
'
:
'
&
'
,
'
<
'
:
'
<
'
,
'
>
'
:
'
>
'
,
'
"
'
:
'
"
'
,
"
'
"
:
'
'
'
,
'
`
'
:
'
`
'
};
var
unescapeMap
=
_
.
invert
(
escapeMap
);
// Functions for escaping and unescaping strings to/from HTML interpolation.
_
.
each
([
'
escape
'
,
'
unescape
'
],
function
(
method
)
{
_
[
method
]
=
function
(
string
)
{
if
(
string
==
null
)
return
''
;
return
(
''
+
string
).
replace
(
entityRegexes
[
method
],
function
(
match
)
{
return
entityMap
[
method
][
match
];
});
var
createEscaper
=
function
(
map
)
{
var
escaper
=
function
(
match
)
{
return
map
[
match
];
};
});
// Regexes for identifying a key that needs to be escaped
var
source
=
'
(?:
'
+
_
.
keys
(
map
).
join
(
'
|
'
)
+
'
)
'
;
var
testRegexp
=
RegExp
(
source
);
var
replaceRegexp
=
RegExp
(
source
,
'
g
'
);
return
function
(
string
)
{
string
=
string
==
null
?
''
:
''
+
string
;
return
testRegexp
.
test
(
string
)
?
string
.
replace
(
replaceRegexp
,
escaper
)
:
string
;
};
};
_
.
escape
=
createEscaper
(
escapeMap
);
_
.
unescape
=
createEscaper
(
unescapeMap
);
// If the value of the named `property` is a function then invoke it with the
// `object` as context; otherwise, return it.
_
.
result
=
function
(
object
,
property
)
{
if
(
object
==
null
)
return
void
0
;
var
value
=
object
[
property
];
return
_
.
isFunction
(
value
)
?
value
.
call
(
object
)
:
value
;
};
// Add your own custom functions to the Underscore object.
_
.
mixin
=
function
(
obj
)
{
each
(
_
.
functions
(
obj
),
function
(
name
)
{
var
func
=
_
[
name
]
=
obj
[
name
];
_
.
prototype
[
name
]
=
function
()
{
var
args
=
[
this
.
_wrapped
];
push
.
apply
(
args
,
arguments
);
return
result
.
call
(
this
,
func
.
apply
(
_
,
args
));
};
});
return
_
.
isFunction
(
value
)
?
object
[
property
]()
:
value
;
};
// Generate a unique integer id (unique within the entire client session).
...
...
@@ -1208,22 +1273,26 @@
'
\\
'
:
'
\\
'
,
'
\r
'
:
'
r
'
,
'
\n
'
:
'
n
'
,
'
\t
'
:
'
t
'
,
'
\
u2028
'
:
'
u2028
'
,
'
\
u2029
'
:
'
u2029
'
};
var
escaper
=
/
\\
|'|
\r
|
\n
|
\t
|
\u
2028|
\u
2029/g
;
var
escaper
=
/
\\
|'|
\r
|
\n
|
\u
2028|
\u
2029/g
;
var
escapeChar
=
function
(
match
)
{
return
'
\\
'
+
escapes
[
match
];
};
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_
.
template
=
function
(
text
,
data
,
settings
)
{
var
render
;
// NB: `oldSettings` only exists for backwards compatibility.
_
.
template
=
function
(
text
,
settings
,
oldSettings
)
{
if
(
!
settings
&&
oldSettings
)
settings
=
oldSettings
;
settings
=
_
.
defaults
({},
settings
,
_
.
templateSettings
);
// Combine delimiters into one regular expression via alternation.
var
matcher
=
new
RegExp
([
var
matcher
=
RegExp
([
(
settings
.
escape
||
noMatch
).
source
,
(
settings
.
interpolate
||
noMatch
).
source
,
(
settings
.
evaluate
||
noMatch
).
source
...
...
@@ -1233,19 +1302,18 @@
var
index
=
0
;
var
source
=
"
__p+='
"
;
text
.
replace
(
matcher
,
function
(
match
,
escape
,
interpolate
,
evaluate
,
offset
)
{
source
+=
text
.
slice
(
index
,
offset
)
.
replace
(
escaper
,
function
(
match
)
{
return
'
\\
'
+
escapes
[
match
];
})
;
source
+=
text
.
slice
(
index
,
offset
)
.
replace
(
escaper
,
escapeChar
);
index
=
offset
+
match
.
length
;
if
(
escape
)
{
source
+=
"
'+
\n
((__t=(
"
+
escape
+
"
))==null?'':_.escape(__t))+
\n
'
"
;
}
if
(
interpolate
)
{
}
else
if
(
interpolate
)
{
source
+=
"
'+
\n
((__t=(
"
+
interpolate
+
"
))==null?'':__t)+
\n
'
"
;
}
if
(
evaluate
)
{
}
else
if
(
evaluate
)
{
source
+=
"
';
\n
"
+
evaluate
+
"
\n
__p+='
"
;
}
index
=
offset
+
match
.
length
;
// Adobe VMs need the match returned to produce the correct offest.
return
match
;
});
source
+=
"
';
\n
"
;
...
...
@@ -1255,29 +1323,31 @@
source
=
"
var __t,__p='',__j=Array.prototype.join,
"
+
"
print=function(){__p+=__j.call(arguments,'');};
\n
"
+
source
+
"
return __p;
\n
"
;
source
+
'
return __p;
\n
'
;
try
{
render
=
new
Function
(
settings
.
variable
||
'
obj
'
,
'
_
'
,
source
);
var
render
=
new
Function
(
settings
.
variable
||
'
obj
'
,
'
_
'
,
source
);
}
catch
(
e
)
{
e
.
source
=
source
;
throw
e
;
}
if
(
data
)
return
render
(
data
,
_
);
var
template
=
function
(
data
)
{
return
render
.
call
(
this
,
data
,
_
);
};
// Provide the compiled function source as a convenience for precompilation.
template
.
source
=
'
function(
'
+
(
settings
.
variable
||
'
obj
'
)
+
'
){
\n
'
+
source
+
'
}
'
;
// Provide the compiled source as a convenience for precompilation.
var
argument
=
settings
.
variable
||
'
obj
'
;
template
.
source
=
'
function(
'
+
argument
+
'
){
\n
'
+
source
+
'
}
'
;
return
template
;
};
// Add a "chain" function
, which will delegate to the wrapper
.
// Add a "chain" function
. Start chaining a wrapped Underscore object
.
_
.
chain
=
function
(
obj
)
{
return
_
(
obj
).
chain
();
var
instance
=
_
(
obj
);
instance
.
_chain
=
true
;
return
instance
;
};
// OOP
...
...
@@ -1291,42 +1361,44 @@
return
this
.
_chain
?
_
(
obj
).
chain
()
:
obj
;
};
// Add your own custom functions to the Underscore object.
_
.
mixin
=
function
(
obj
)
{
_
.
each
(
_
.
functions
(
obj
),
function
(
name
)
{
var
func
=
_
[
name
]
=
obj
[
name
];
_
.
prototype
[
name
]
=
function
()
{
var
args
=
[
this
.
_wrapped
];
push
.
apply
(
args
,
arguments
);
return
result
.
call
(
this
,
func
.
apply
(
_
,
args
));
};
});
};
// Add all of the Underscore functions to the wrapper object.
_
.
mixin
(
_
);
// Add all mutator Array functions to the wrapper.
each
([
'
pop
'
,
'
push
'
,
'
reverse
'
,
'
shift
'
,
'
sort
'
,
'
splice
'
,
'
unshift
'
],
function
(
name
)
{
_
.
each
([
'
pop
'
,
'
push
'
,
'
reverse
'
,
'
shift
'
,
'
sort
'
,
'
splice
'
,
'
unshift
'
],
function
(
name
)
{
var
method
=
ArrayProto
[
name
];
_
.
prototype
[
name
]
=
function
()
{
var
obj
=
this
.
_wrapped
;
method
.
apply
(
obj
,
arguments
);
if
((
name
==
'
shift
'
||
name
==
'
splice
'
)
&&
obj
.
length
===
0
)
delete
obj
[
0
];
if
((
name
==
=
'
shift
'
||
name
=
==
'
splice
'
)
&&
obj
.
length
===
0
)
delete
obj
[
0
];
return
result
.
call
(
this
,
obj
);
};
});
// Add all accessor Array functions to the wrapper.
each
([
'
concat
'
,
'
join
'
,
'
slice
'
],
function
(
name
)
{
_
.
each
([
'
concat
'
,
'
join
'
,
'
slice
'
],
function
(
name
)
{
var
method
=
ArrayProto
[
name
];
_
.
prototype
[
name
]
=
function
()
{
return
result
.
call
(
this
,
method
.
apply
(
this
.
_wrapped
,
arguments
));
};
});
_
.
extend
(
_
.
prototype
,
{
// 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
;
}
});
// Extracts the result from a wrapped and chained object.
_
.
prototype
.
value
=
function
()
{
return
this
.
_wrapped
;
};
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
...
...
@@ -1340,4 +1412,4 @@
return
_
;
});
}
}
).
call
(
this
);
}
.
call
(
this
)
);
examples/backbone/index.html
View file @
e80de6d1
...
...
@@ -49,7 +49,7 @@
<%
}
%>
</script>
<script
src=
"bower_components/todomvc-common/base.js"
></script>
<script
src=
"bower_components/jquery/jquery.js"
></script>
<script
src=
"bower_components/jquery/
dist/
jquery.js"
></script>
<script
src=
"bower_components/underscore/underscore.js"
></script>
<script
src=
"bower_components/backbone/backbone.js"
></script>
<script
src=
"bower_components/backbone.localStorage/backbone.localStorage.js"
></script>
...
...
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