';
- },
-
- start: function () {
- this._router.run(function (Handler, state) {
- //console.log('!!! Router router run', state.path);
- this._state = state;
- NavActions.routeChange(state);
- var factory = React.createFactory(Handler);
- var appElement = document.getElementById(this._containerId);
- if (appElement) {
- React.render(factory(), appElement);
- }
- }.bind(this));
- },
-
- // Wrap react-router.Navigation
-
- makePath: function (routeName, params, query) {
- return(this._router.makePath(routeName, params, query));
- },
-
- transitionTo: function (routeName, params, query) {
- this._router.transitionTo(routeName, params, query);
- },
-
- replaceWith: function (routeName, params, query) {
- this._router.replaceWith(routeName, params, query);
- },
-
- updateParam: function (name, value) {
- var obj = {};
- obj[name] = value;
- return _.extend({}, this._state.params, obj);
- },
-
- updateQueryParam: function (name, value) {
- var obj = {};
- obj[name] = value;
- return _.extend({}, this._state.query, obj);
- },
-
- makeHrefParam: function (name, value) {
- return this._router.makeHref(
- this._state.routes[this._state.routes.length-1].name,
- this.updateQueryParam(name, value),
- this._state.query);
- },
-
- transitionToParam: function (name, value) {
- this._router.transitionTo(
- this._state.routes[this._state.routes.length-1].name,
- this.updateQueryParam(name, value),
- this._state.query);
- },
-
- replaceParam: function (name, value) {
- this._router.replaceWith(
- this._state.routes[this._state.routes.length-1].name,
- this.updateQueryParam(name, value),
- this._state.query);
- },
-
- replaceQueryParam: function (name, value) {
- this._router.replaceWith(
- this._state.routes[this._state.routes.length-1].name,
- this._state.params,
- this.updateQueryParam(name, value));
- },
-
- makeHref: function (route) {
- return route; //this._router.makeHref(route, params, query);
- },
-
- isActive: function (routeName) {
- return this._state.routes.some(function (route) {
- return route.name === routeName;
- });
- },
-
- param: function (name) {
- return this._state ? this._state.params[name] : null;
- },
-
- queryParams: function () {
- return this._state.query;
- },
-
- queryParam: function (name) {
- return this._state ? this._state.query[name] : null;
- }
- };
-
-
-/***/ },
-/* 3 */
-/***/ function(module, exports, __webpack_require__) {
-
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
-
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var App = React.createClass({displayName: "App",
@@ -317,12 +145,12 @@ var Grommet =
/***/ },
-/* 4 */
+/* 2 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var CheckBox = React.createClass({displayName: "CheckBox",
@@ -351,11 +179,11 @@ var Grommet =
/***/ },
-/* 5 */
+/* 3 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var GrommetDocument = React.createClass({displayName: "GrommetDocument",
@@ -383,12 +211,14 @@ var Grommet =
/***/ },
-/* 6 */
+/* 4 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
+
+ var BASE_SIZE = 192;
function polarToCartesian (centerX, centerY, radius, angleInDegrees) {
var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
@@ -412,7 +242,7 @@ var Grommet =
var Donut = React.createClass({displayName: "Donut",
propTypes: {
- key: React.PropTypes.bool,
+ legend: React.PropTypes.bool,
series: React.PropTypes.arrayOf(React.PropTypes.shape({
label: React.PropTypes.string,
value: React.PropTypes.number,
@@ -421,7 +251,8 @@ var Grommet =
React.PropTypes.string // status
]),
onClick: React.PropTypes.func
- })).isRequired
+ })).isRequired,
+ units: React.PropTypes.string
},
_initialTimeout: function () {
@@ -437,21 +268,96 @@ var Grommet =
this.setState({initial: false, activeIndex: 0});
},
+ _onResize: function() {
+ // orientation based on available window orientation
+ var ratio = window.innerWidth / window.innerHeight;
+ if (ratio < 0.8) {
+ this.setState({orientation: 'portrait'});
+ } else if (ratio > 1.2) {
+ this.setState({orientation: 'landscape'});
+ }
+ // content based on avialable real estate
+ var parentElement = this.refs.donut.getDOMNode().parentNode;
+ var width = parentElement.offsetWidth;
+ var height = parentElement.offsetHeight;
+ if (height < BASE_SIZE || width < BASE_SIZE ||
+ (width < (BASE_SIZE * 2) && height < (BASE_SIZE * 2))) {
+ this.setState({size: 'small'});
+ } else {
+ this.setState({size: null});
+ }
+ },
+
getInitialState: function() {
- return {initial: true, activeIndex: 0};
+ return {
+ initial: true,
+ activeIndex: 0,
+ legend: false,
+ orientation: 'portrait'
+ };
},
componentDidMount: function() {
this._timeout = setTimeout(this._initialTimeout, 10);
this.setState({initial: true, activeIndex: 0});
+ window.addEventListener('resize', this._onResize);
+ setTimeout(this._onResize, 10);
},
componentWillUnmount: function() {
clearTimeout(this._timeout);
this._timeout = null;
+ window.removeEventListener('resize', this._onResize);
+ },
+
+ _itemColorIndex: function (item, index) {
+ return item.colorIndex || ('graph-' + (index + 1));
+ },
+
+ _renderLegend: function () {
+ var total = 0;
+
+ var legends = this.props.series.map(function (item, index) {
+ var legendClasses = ["donut__legend-item"];
+ if (this.state.activeIndex === index) {
+ legendClasses.push("donut__legend-item--active");
+ }
+ var colorIndex = this._itemColorIndex(item, index);
+ total += item.value;
+
+ return(
+ React.createElement("li", {key: item.label, className: legendClasses.join(' '),
+ onMouseOver: this._onMouseOver.bind(this, index),
+ onMouseOut: this._onMouseOut.bind(this, index)},
+ React.createElement("svg", {className: "donut__legend-item-swatch color-index-" + colorIndex,
+ viewBox: "0 0 12 12"},
+ React.createElement("path", {className: item.className, d: "M 5 0 l 0 12"})
+ ),
+ React.createElement("span", {className: "donut__legend-item-label"}, item.label),
+ React.createElement("span", {className: "donut__legend-item-value"}, item.value),
+ React.createElement("span", {className: "donut__legend-item-units"}, this.props.units)
+ )
+ );
+ }, this);
+
+ return (
+ React.createElement("ol", {className: "donut__legend"},
+ legends,
+ React.createElement("li", {className: "donut__legend-total"},
+ React.createElement("span", {className: "donut__legend-total-label"}, "Total"),
+ React.createElement("span", {className: "donut__legend-total-value"}, total),
+ React.createElement("span", {className: "donut__legend-total-units"}, this.props.units)
+ )
+ )
+ );
},
render: function() {
+ var classes = ["donut", "donut--" + this.state.orientation];
+ if (this.state.size) {
+ classes.push("donut--" + this.state.size);
+ }
+
var total = 0;
this.props.series.some(function (item) {
total += item.value;
@@ -459,22 +365,20 @@ var Grommet =
var startAngle = 0;
var anglePer = 360.0 / total;
- var paths = {};
- var keys = {};
var value = null;
var units = null;
var label = null;
- this.props.series.forEach(function (item, index) {
+ var paths = this.props.series.map(function (item, index) {
var endAngle = Math.min(360, Math.max(10, startAngle + (anglePer * item.value)));
var radius = (this.state.activeIndex === index) ? 78 : 72;
- var commands = describeArc(96, 96, radius, startAngle, endAngle-2);
+ var commands = describeArc(BASE_SIZE/2, BASE_SIZE/2, radius, startAngle, endAngle-2);
startAngle = endAngle;
- var colorIndex = item.colorIndex || (index + 1);
+ var colorIndex = this._itemColorIndex(item, index);
var sliceClasses = ["donut__slice"];
- sliceClasses.push("donut__slice--color-index-" + colorIndex);
+ sliceClasses.push("color-index-" + colorIndex);
if (this.state.activeIndex === index) {
sliceClasses.push("donut__slice--active");
value = item.value;
@@ -482,38 +386,24 @@ var Grommet =
label = item.label;
}
- paths[colorIndex] = (
- React.createElement("path", {fill: "none", className: sliceClasses.join(' '), d: commands,
+ return(
+ React.createElement("path", {key: item.label, fill: "none", className: sliceClasses.join(' '), d: commands,
onMouseOver: this._onMouseOver.bind(null, index),
onMouseOut: this._onMouseOut.bind(null, index),
onClick: item.onClick})
);
-
- if (this.props.key) {
-
- var keyItemClasses = ["donut__key-item"];
- if (this.state.activeIndex === index) {
- keyItemClasses.push("donut__key-item--active");
- }
-
- keys[colorIndex] = (
- React.createElement("li", {key: item.className, className: keyItemClasses.join(' '),
- onMouseOver: this._onMouseOver.bind(null, index),
- onMouseOut: this._onMouseOut.bind(null, index)},
- React.createElement("svg", {className: "donut__key-item-swatch", viewBox: "0 0 12 12"},
- React.createElement("path", {className: item.className, d: "M 5 0 l 0 12"})
- ),
- React.createElement("span", {className: "donut__key-item-label"}, item.label),
- React.createElement("span", {className: "donut__key-item-value"}, item.value)
- )
- );
- }
}, this);
+ var legend = null;
+ if (this.props.legend) {
+ legend = this._renderLegend();
+ }
+
return (
- React.createElement("div", {className: "donut"},
+ React.createElement("div", {ref: "donut", className: classes.join(' ')},
React.createElement("div", {className: "donut__graphic-container"},
- React.createElement("svg", {className: "donut__graphic", viewBox: "0 0 192 192",
+ React.createElement("svg", {className: "donut__graphic",
+ viewBox: "0 0 " + BASE_SIZE + " " + BASE_SIZE,
preserveAspectRatio: "xMidYMid meet"},
React.createElement("g", null, paths)
),
@@ -522,13 +412,10 @@ var Grommet =
value,
React.createElement("span", {className: "donut__active-units"}, units)
),
-
React.createElement("div", {className: "donut__active-label"}, label)
)
),
- React.createElement("ol", {className: "donut__key"},
- keys
- )
+ legend
)
);
}
@@ -539,12 +426,12 @@ var Grommet =
/***/ },
-/* 7 */
+/* 5 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var CLASS_ROOT = "fixed-header";
@@ -590,13 +477,13 @@ var Grommet =
/***/ },
-/* 8 */
+/* 6 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
- var Top = __webpack_require__(50);
+ var React = __webpack_require__(43);
+ var Top = __webpack_require__(44);
var Footer = React.createClass({displayName: "Footer",
@@ -685,12 +572,12 @@ var Grommet =
/***/ },
-/* 9 */
+/* 7 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Form = React.createClass({displayName: "Form",
@@ -720,12 +607,12 @@ var Grommet =
/***/ },
-/* 10 */
+/* 8 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var FormField = React.createClass({displayName: "FormField",
@@ -767,27 +654,35 @@ var Grommet =
/***/ },
-/* 11 */
+/* 9 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Header = React.createClass({displayName: "Header",
propTypes: {
colorIndex: React.PropTypes.string,
+ flush: React.PropTypes.bool,
large: React.PropTypes.bool,
primary: React.PropTypes.bool,
small: React.PropTypes.bool
},
+ getDefaultProps: function () {
+ return {flush: true, large: false, primary: false, small: false};
+ },
+
render: function() {
var classes = ["header"];
if (this.props.primary) {
classes.push("header--primary");
}
+ if (this.props.flush) {
+ classes.push("header--flush");
+ }
if (this.props.large) {
classes.push("header--large");
}
@@ -819,12 +714,12 @@ var Grommet =
/***/ },
-/* 12 */
+/* 10 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Label = React.createClass({displayName: "Label",
@@ -856,44 +751,12 @@ var Grommet =
/***/ },
-/* 13 */
-/***/ function(module, exports, __webpack_require__) {
-
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
-
- var React = __webpack_require__(48);
- var Router = __webpack_require__(2);
-
- var Link = React.createClass({displayName: "Link",
-
- _onClick: function (event) {
- event.preventDefault();
- if (this.props.onClick) {
- this.props.onClick(event);
- }
- Router.transitionTo(event.currentTarget.getAttribute('href'));
- },
-
- render: function() {
- return (
- React.createElement("a", {className: this.props.className, href: this.props.href, onClick: this._onClick},
- this.props.children
- )
- );
- }
-
- });
-
- module.exports = Link;
-
-
-/***/ },
-/* 14 */
+/* 11 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Login = React.createClass({displayName: "Login",
@@ -921,7 +784,7 @@ var Grommet =
componentDidMount: function() {
window.addEventListener('resize', this._onResize);
- setTimeout(this.adjustBackground, 10);
+ setTimeout(this.adjustBackground, 300);
},
componentWillUnmount: function() {
@@ -957,13 +820,13 @@ var Grommet =
/***/ },
-/* 15 */
+/* 12 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
- var CheckBox = __webpack_require__(4);
+ var React = __webpack_require__(43);
+ var CheckBox = __webpack_require__(2);
var CLASS_ROOT = "login-form";
@@ -1062,17 +925,17 @@ var Grommet =
/***/ },
-/* 16 */
+/* 13 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
- var ReactLayeredComponent = __webpack_require__(42);
- var KeyboardAccelerators = __webpack_require__(41);
- var Overlay = __webpack_require__(51);
- var MoreIcon = __webpack_require__(34);
- var DropCaretIcon = __webpack_require__(52);
+ var React = __webpack_require__(43);
+ var ReactLayeredComponent = __webpack_require__(39);
+ var KeyboardAccelerators = __webpack_require__(38);
+ var Overlay = __webpack_require__(45);
+ var MoreIcon = __webpack_require__(31);
+ var DropCaretIcon = __webpack_require__(46);
var Menu = React.createClass({displayName: "Menu",
@@ -1305,12 +1168,12 @@ var Grommet =
/***/ },
-/* 17 */
+/* 14 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var BASE_WIDTH = 192;
var BASE_HEIGHT = 24;
@@ -1376,11 +1239,11 @@ var Grommet =
/***/ },
-/* 18 */
+/* 15 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Panel = React.createClass({displayName: "Panel",
@@ -1416,12 +1279,12 @@ var Grommet =
/***/ },
-/* 19 */
+/* 16 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var RadioButton = React.createClass({displayName: "RadioButton",
@@ -1450,16 +1313,16 @@ var Grommet =
/***/ },
-/* 20 */
+/* 17 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
- var ReactLayeredComponent = __webpack_require__(42);
- var KeyboardAccelerators = __webpack_require__(41);
- var Overlay = __webpack_require__(51);
- var SearchIcon = __webpack_require__(37);
+ var React = __webpack_require__(43);
+ var ReactLayeredComponent = __webpack_require__(39);
+ var KeyboardAccelerators = __webpack_require__(38);
+ var Overlay = __webpack_require__(45);
+ var SearchIcon = __webpack_require__(34);
var CLASS_ROOT = "search";
@@ -1729,12 +1592,12 @@ var Grommet =
/***/ },
-/* 21 */
+/* 18 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var CLASS_ROOT = 'search-combo';
@@ -1755,12 +1618,12 @@ var Grommet =
/***/ },
-/* 22 */
+/* 19 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Section = React.createClass({displayName: "Section",
@@ -1820,12 +1683,12 @@ var Grommet =
/***/ },
-/* 23 */
+/* 20 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Table = React.createClass({displayName: "Table",
@@ -1894,22 +1757,34 @@ var Grommet =
/***/ },
-/* 24 */
+/* 21 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Tiles = React.createClass({displayName: "Tiles",
propTypes: {
+ fill: React.PropTypes.bool,
+ flush: React.PropTypes.bool,
small: React.PropTypes.bool
},
+ getDefaultProps: function () {
+ return {flush: true, fill: false, small: false};
+ },
+
// children should be an array of Tile
render: function () {
var classes = ["tiles"];
+ if (this.props.fill) {
+ classes.push("tiles--fill");
+ }
+ if (this.props.flush) {
+ classes.push("tiles--flush");
+ }
if (this.props.small) {
classes.push("tiles--small");
}
@@ -1929,17 +1804,18 @@ var Grommet =
/***/ },
-/* 25 */
+/* 22 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Tile = React.createClass({displayName: "Tile",
propTypes: {
- status: React.PropTypes.string
+ status: React.PropTypes.string,
+ wide: React.PropTypes.bool
},
render: function() {
@@ -1947,6 +1823,9 @@ var Grommet =
if (this.props.status) {
classes.push("tile--status-" + this.props.status.toLowerCase());
}
+ if (this.props.wide) {
+ classes.push("tile--wide");
+ }
if (this.props.className) {
classes.push(this.props.className);
}
@@ -1964,13 +1843,13 @@ var Grommet =
/***/ },
-/* 26 */
+/* 23 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
- var DropCaret = __webpack_require__(52);
+ var React = __webpack_require__(43);
+ var DropCaret = __webpack_require__(46);
var Title = React.createClass({displayName: "Title",
@@ -2003,13 +1882,13 @@ var Grommet =
/***/ },
-/* 27 */
+/* 24 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var _ = __webpack_require__(79);
- var React = __webpack_require__(48);
+ var _ = __webpack_require__(54);
+ var React = __webpack_require__(43);
function renderObject (obj) {
var attrs = [];
@@ -2069,12 +1948,12 @@ var Grommet =
/***/ },
-/* 28 */
+/* 25 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var TBD = React.createClass({displayName: "TBD",
@@ -2092,12 +1971,12 @@ var Grommet =
/***/ },
-/* 29 */
+/* 26 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Clear = React.createClass({displayName: "Clear",
@@ -2122,12 +2001,12 @@ var Grommet =
/***/ },
-/* 30 */
+/* 27 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var DragHandle = React.createClass({displayName: "DragHandle",
@@ -2158,12 +2037,12 @@ var Grommet =
/***/ },
-/* 31 */
+/* 28 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Edit = React.createClass({displayName: "Edit",
@@ -2197,12 +2076,12 @@ var Grommet =
/***/ },
-/* 32 */
+/* 29 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Filter = React.createClass({displayName: "Filter",
@@ -2226,12 +2105,12 @@ var Grommet =
/***/ },
-/* 33 */
+/* 30 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Help = React.createClass({displayName: "Help",
@@ -2257,12 +2136,12 @@ var Grommet =
/***/ },
-/* 34 */
+/* 31 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var More = React.createClass({displayName: "More",
@@ -2289,12 +2168,12 @@ var Grommet =
/***/ },
-/* 35 */
+/* 32 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Next = React.createClass({displayName: "Next",
@@ -2319,12 +2198,12 @@ var Grommet =
/***/ },
-/* 36 */
+/* 33 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Previous = React.createClass({displayName: "Previous",
@@ -2349,12 +2228,12 @@ var Grommet =
/***/ },
-/* 37 */
+/* 34 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Search = React.createClass({displayName: "Search",
@@ -2379,12 +2258,12 @@ var Grommet =
/***/ },
-/* 38 */
+/* 35 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var SearchPlus = React.createClass({displayName: "SearchPlus",
@@ -2411,12 +2290,12 @@ var Grommet =
/***/ },
-/* 39 */
+/* 36 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var CLASS_ROOT = "icon-spinning";
@@ -2444,18 +2323,18 @@ var Grommet =
/***/ },
-/* 40 */
+/* 37 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
- var OK = __webpack_require__(54);
- var ErrorStatus = __webpack_require__(55);
- var Warning = __webpack_require__(56);
- var Disabled = __webpack_require__(57);
- var Unknown = __webpack_require__(58);
- var Label = __webpack_require__(59);
+ var React = __webpack_require__(43);
+ var OK = __webpack_require__(48);
+ var ErrorStatus = __webpack_require__(49);
+ var Warning = __webpack_require__(50);
+ var Disabled = __webpack_require__(51);
+ var Unknown = __webpack_require__(52);
+ var Label = __webpack_require__(53);
var CLASS_ROOT = "status-icon";
@@ -2511,7 +2390,7 @@ var Grommet =
/***/ },
-/* 41 */
+/* 38 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
@@ -2611,14 +2490,14 @@ var Grommet =
/***/ },
-/* 42 */
+/* 39 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
// http://jsfiddle.net/LBAr8/
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var ReactLayeredComponent = {
@@ -2652,381 +2531,199 @@ var Grommet =
/***/ },
-/* 43 */
+/* 40 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var mirrorkey = __webpack_require__(83);
+ var Reflux = __webpack_require__(55);
+ var Rest = __webpack_require__(42);
- module.exports = {
+ var Actions = Reflux.createActions({
+ // Session
+ 'login': {asyncResult: true},
+ 'logout': {}
+ });
- CHANGE_EVENT: 'change',
+ Actions.login.listen(function(username, password) {
+ var thisAction = this;
+ Rest.post('/rest/login-sessions',
+ {authLoginDomain: 'LOCAL', userName: username, password: password, loginMsgAck: true})
+ .end(function(err, res) {
+ if (err) {
+ return thisAction.failed(err, res.body);
+ }
+ if (!res.ok) {
+ return thisAction.failed(err, res.body);
+ }
+ thisAction.completed(username, res.body.sessionID);
+ });
+ });
- ActionTypes: mirrorkey({
- // remove?
- NAV_SETUP: null,
- NAV_SEARCH: null,
- NAV_SEARCH_SUGGESTIONS_RESULT: null,
- NAV_CHANGE: null,
- ROUTE_CHANGE: null,
+ module.exports = Actions;
- SESSION_SETUP: null,
- SESSION_LOGOUT: null,
- SESSION_LOGIN: null
- }),
- ActionSources: mirrorkey({
- SERVER_ACTION: null,
- VIEW_ACTION: null
- }),
+/***/ },
+/* 41 */
+/***/ function(module, exports, __webpack_require__) {
- Request: mirrorkey({
- SUCCESS: null,
- TIMEOUT: null,
- ERROR: null
- })
+ // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- };
+ var Reflux = __webpack_require__(55);
+ var Actions = __webpack_require__(40);
+ var Cookies = __webpack_require__(47);
+ var TOKEN = "token";
+ var USER = "user";
+ var LOGIN_TIME = "loginTime";
+ var EMAIL = "email";
-/***/ },
-/* 44 */
-/***/ function(module, exports, __webpack_require__) {
+ var SessionStore = Reflux.createStore({
- // (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ _data: {
+ id: null,
+ name: null,
+ created: null,
+ email: null,
+ loginError: null // {message: , resolution: }
+ },
- var _ = __webpack_require__(79);
- var Dispatcher = __webpack_require__(80).Dispatcher;
- var Constants = __webpack_require__(43);
+ init: function () {
+ this._data.id = Cookies.get(TOKEN);
+ this._data.name = Cookies.get(USER);
+ this._data.created = Cookies.get(LOGIN_TIME);
+ this._data.email = Cookies.get(EMAIL);
- var AppDispatcher = _.extend(new Dispatcher(), {
+ this.listenTo(Actions.login.completed, this._onLoginCompleted);
+ this.listenTo(Actions.login.failed, this._onLoginFailed);
+ this.listenTo(Actions.logout, this._onLogout);
+ },
- handleServerAction: function(action) {
- var payload = {
- source: Constants.ActionSources.SERVER_ACTION,
- action: action
- };
- this.dispatch(payload);
+ _onLoginCompleted: function (username, id) {
+ this._data.id = id;
+ this._data.name = username;
+ this._data.created = new Date();
+ this._data.loginError = null;
+ if (username.indexOf('@') !== -1) {
+ this._data.email = username;
+ }
+ Cookies.set(TOKEN, this._data.id);
+ Cookies.set(USER, this._data.name);
+ Cookies.set(LOGIN_TIME, this._data.created);
+ Cookies.set(EMAIL, this._data.email);
+ this.trigger(this._data);
},
- handleViewAction: function(action) {
- var payload = {
- source: Constants.ActionSources.VIEW_ACTION,
- action: action
+ _onLoginFailed: function (error, response) {
+ this._data.loginError = {
+ message: response.message,
+ resolution: response.resolution
};
- this.dispatch(payload);
- }
+ this.trigger(this._data);
+ },
- });
-
- module.exports = AppDispatcher;
-
-
-/***/ },
-/* 45 */
-/***/ function(module, exports, __webpack_require__) {
-
- // (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
-
- var _ = __webpack_require__(79);
- var AppDispatcher = __webpack_require__(44);
- var EventEmitter = __webpack_require__(81).EventEmitter;
- var Constants = __webpack_require__(43);
- var Cookies = __webpack_require__(53);
-
- var TOKEN = "token";
- var USER = "user";
- var LOGIN_TIME = "loginTime";
- var EMAIL = "email";
-
- var _data = {
- id: null,
- name: null,
- created: null,
- email: null,
- loginError: null // {message: , resolution: }
- };
-
- function setup () {
- _data.id = Cookies.get(TOKEN);
- _data.name = Cookies.get(USER);
- _data.created = Cookies.get(LOGIN_TIME);
- _data.email = Cookies.get(EMAIL);
- }
-
- function login(username, id) {
- _data.id = id;
- _data.name = username;
- _data.created = new Date();
- _data.loginError = null;
- if (username.indexOf('@') !== -1) {
- _data.email = username;
- }
- Cookies.set(TOKEN, _data.id);
- Cookies.set(USER, _data.name);
- Cookies.set(LOGIN_TIME, _data.created);
- Cookies.set(EMAIL, _data.email);
- }
-
- function setLoginError(message, resolution) {
- _data.loginError = {
- message: message,
- resolution: resolution
- };
- }
-
- function logout() {
- _data.id = null;
- _data.name = null;
- _data.created = null;
- Cookies.remove(TOKEN);
- Cookies.remove(USER);
- Cookies.remove(LOGIN_TIME);
- }
-
- var SessionStore = _.extend({}, EventEmitter.prototype, {
-
- // public methods used by Controller-View to operate on data
- getAll: function() {
- return _data;
- },
-
- // Allow Controller-View to register itself with store
- addChangeListener: function(callback) {
- this.on(Constants.CHANGE_EVENT, callback);
- },
- removeChangeListener: function(callback) {
- this.removeListener(Constants.CHANGE_EVENT, callback);
+ _onLogout: function () {
+ this._data.id = null;
+ this._data.name = null;
+ this._data.created = null;
+ this._data.email = null;
+ Cookies.remove(TOKEN);
+ Cookies.remove(USER);
+ Cookies.remove(LOGIN_TIME);
+ Cookies.remove(EMAIL);
+ this.trigger(this._data);
},
- // triggers change listener above, firing controller-view callback
- emitChange: function() {
- this.emit(Constants.CHANGE_EVENT);
- },
-
- // register store with dispatcher, allowing actions to flow through
- dispatcherIndex: AppDispatcher.register(function(payload) {
- var action = payload.action;
-
- switch(action.type) {
-
- case Constants.ActionTypes.SESSION_SETUP:
- setup();
- SessionStore.emitChange();
- break;
-
- case Constants.ActionTypes.SESSION_LOGOUT:
- logout();
- SessionStore.emitChange();
- break;
-
- case Constants.ActionTypes.SESSION_LOGIN:
- if (Constants.Request.SUCCESS === action.result) {
- login(action.context.username, action.response.sessionID);
- } else if (Constants.Request.ERROR === action.result) {
- setLoginError(action.response.message, action.response.recommendedActions);
- }
- SessionStore.emitChange();
- break;
-
- }
- })
+ getInitialState: function () {
+ return this._data;
+ }
});
module.exports = SessionStore;
/***/ },
-/* 46 */
+/* 42 */
/***/ function(module, exports, __webpack_require__) {
- // (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
-
- // portions leveraged from examples at
- // http://www.code-experience.com/async-requests-with-react-js-and-flux-revisited/
-
- var _ = __webpack_require__(79);
- var AppDispatcher = __webpack_require__(44);
- var Constants = __webpack_require__(43);
- var SessionStore = __webpack_require__(45);
- var request = __webpack_require__(95);
-
- var VERSION = 200;
- var TIMEOUT = 10000;
- var PREFIX = '';
-
- function token() {
- return SessionStore.getAll().id;
- }
+ // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- function dispatch(key, result, response, params, context) {
- var payload = {type: key, result: result, response: response};
- if (params) {
- payload.queryParams = params;
- }
- if (context) {
- payload.context = context;
- }
- AppDispatcher.handleServerAction(payload);
- }
+ var request = __webpack_require__(56);
- // return successful response, else return request Constants
- function responseHandler(key, params, context) {
- return function (err, res) {
- if (err && err.timeout === TIMEOUT) {
- dispatch(key, Constants.Request.TIMEOUT, null, params, context);
- } else if (res.status === 400 &&
- Constants.ActionTypes.LOGOUT !== key &&
- Constants.ActionTypes.LOGIN !== key) {
- dispatch(Constants.ActionTypes.LOGOUT, null, null, params, context);
- } else if (!res.ok) {
- dispatch(key, Constants.Request.ERROR, res.body, params, context);
- } else {
- dispatch(key, Constants.Request.SUCCESS, res.body, params, context);
- }
- };
- }
+ var _headers = {};
- function deliver(req, key, params, context) {
- req.timeout(TIMEOUT);
- if (token()) {
- req.set('auth', token());
- }
- req.set('Accept', 'application/json');
- req.set('X-API-Version', VERSION);
- req.end(responseHandler(key, params, context));
- }
+ var _timeout = 10000; // 10s
// convert params to string, to deal with array values
function buildQueryParams(params) {
var result = [];
- _.forOwn(params, function (value, name) {
- if (Array.isArray(value)) {
- for (var i=0; i 0) {
- Api.get(Constants.ActionTypes.NAV_SEARCH_SUGGESTIONS_RESULT,
- '/rest/index/resources',
- {start: 0, count: 5, userQuery: text});
- }
- },
-
- routeChange: function (routerState) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.ROUTE_CHANGE,
- routerState: routerState
- });
- }
-
- };
-
+ module.exports = React;
/***/ },
-/* 50 */
+/* 44 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Top = React.createClass({displayName: "Top",
@@ -3053,7 +2750,7 @@ var Grommet =
/***/ },
-/* 51 */
+/* 45 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
@@ -3159,12 +2856,12 @@ var Grommet =
/***/ },
-/* 52 */
+/* 46 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var DropCaret = React.createClass({displayName: "DropCaret",
@@ -3189,7 +2886,7 @@ var Grommet =
/***/ },
-/* 53 */
+/* 47 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
@@ -3246,7 +2943,7 @@ var Grommet =
return true;
},
remove: function (sKey, sPath, sDomain) {
- if (!this.hasItem(sKey)) { return false; }
+ if (!this.has(sKey)) { return false; }
document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
return true;
},
@@ -3265,12 +2962,12 @@ var Grommet =
/***/ },
-/* 54 */
+/* 48 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var OK = React.createClass({displayName: "OK",
@@ -3297,12 +2994,12 @@ var Grommet =
/***/ },
-/* 55 */
+/* 49 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var ErrorStatus = React.createClass({displayName: "ErrorStatus",
@@ -3329,12 +3026,12 @@ var Grommet =
/***/ },
-/* 56 */
+/* 50 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Warning = React.createClass({displayName: "Warning",
@@ -3361,12 +3058,12 @@ var Grommet =
/***/ },
-/* 57 */
+/* 51 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Disabled = React.createClass({displayName: "Disabled",
@@ -3393,12 +3090,12 @@ var Grommet =
/***/ },
-/* 58 */
+/* 52 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Unknown = React.createClass({displayName: "Unknown",
@@ -3425,12 +3122,12 @@ var Grommet =
/***/ },
-/* 59 */
+/* 53 */
/***/ function(module, exports, __webpack_require__) {
// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
- var React = __webpack_require__(48);
+ var React = __webpack_require__(43);
var Label = React.createClass({displayName: "Label",
@@ -3454,9534 +3151,9638 @@ var Grommet =
/***/ },
-/* 60 */
+/* 54 */
/***/ function(module, exports, __webpack_require__) {
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/**
+ * @license
+ * lodash 3.8.0 (Custom Build)
+ * Build: `lodash modern -d -o ./index.js`
+ * Copyright 2012-2015 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+ ;(function() {
- var Router = __webpack_require__(2);
+ /** Used as a safe reference for `undefined` in pre-ES5 environments. */
+ var undefined;
- var _config;
+ /** Used as the semantic version number. */
+ var VERSION = '3.8.0';
- function configForCategory(category) {
- var result;
- if (Array.isArray(category)) {
- category.some(function (singleCategory) {
- if (_config[singleCategory]) {
- result = _config[singleCategory];
- return true;
- }
- });
- } else {
- result = _config[category];
- }
- return result;
- }
+ /** Used to compose bitmasks for wrapper metadata. */
+ var BIND_FLAG = 1,
+ BIND_KEY_FLAG = 2,
+ CURRY_BOUND_FLAG = 4,
+ CURRY_FLAG = 8,
+ CURRY_RIGHT_FLAG = 16,
+ PARTIAL_FLAG = 32,
+ PARTIAL_RIGHT_FLAG = 64,
+ ARY_FLAG = 128,
+ REARG_FLAG = 256;
- module.exports = {
+ /** Used as default options for `_.trunc`. */
+ var DEFAULT_TRUNC_LENGTH = 30,
+ DEFAULT_TRUNC_OMISSION = '...';
- init: function (config) {
- _config = config;
- },
+ /** Used to detect when a function becomes hot. */
+ var HOT_COUNT = 150,
+ HOT_SPAN = 16;
- resourceHref: function (category, uri, query) {
- var config = configForCategory(category);
- return (config ? Router.makeHref(config.resourceRoute, {splat: uri}, query) : '');
- },
+ /** Used to indicate the type of lazy iteratees. */
+ var LAZY_DROP_WHILE_FLAG = 0,
+ LAZY_FILTER_FLAG = 1,
+ LAZY_MAP_FLAG = 2;
- categoryHref: function (category, query) {
- var config = configForCategory(category);
- return (config ? Router.makeHref(config.route, {}, query) : '');
- },
+ /** Used as the `TypeError` message for "Functions" methods. */
+ var FUNC_ERROR_TEXT = 'Expected a function';
- categoryRoute: function (category) {
- var config = configForCategory(category);
- return (config ? config.route : '');
- },
+ /** Used as the internal argument placeholder. */
+ var PLACEHOLDER = '__lodash_placeholder__';
- resourceRoute: function (category) {
- var config = configForCategory(category);
- return (config ? config.resourceRoute : '');
- },
+ /** `Object#toString` result references. */
+ var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ errorTag = '[object Error]',
+ funcTag = '[object Function]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ objectTag = '[object Object]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ weakMapTag = '[object WeakMap]';
- categoryLabel: function (category) {
- var config = configForCategory(category);
- return (config ? config.label : '');
- }
- };
+ var arrayBufferTag = '[object ArrayBuffer]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+ /** Used to match empty string literals in compiled template source. */
+ var reEmptyStringLeading = /\b__p \+= '';/g,
+ reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
-/***/ },
-/* 61 */
-/***/ function(module, exports, __webpack_require__) {
+ /** Used to match HTML entities and HTML characters. */
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
+ reUnescapedHtml = /[&<>"'`]/g,
+ reHasEscapedHtml = RegExp(reEscapedHtml.source),
+ reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ /** Used to match template delimiters. */
+ var reEscape = /<%-([\s\S]+?)%>/g,
+ reEvaluate = /<%([\s\S]+?)%>/g,
+ reInterpolate = /<%=([\s\S]+?)%>/g;
- var React = __webpack_require__(48);
- var Index = __webpack_require__(69);
- var IndexRouter = __webpack_require__(60);
- var Link = __webpack_require__(13);
+ /** Used to match property names within property paths. */
+ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,
+ reIsPlainProp = /^\w*$/,
+ rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
- var Activity = React.createClass({displayName: "Activity",
+ /**
+ * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special).
+ * In addition to special characters the forward slash is escaped to allow for
+ * easier `eval` use and `Function` compilation.
+ */
+ var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
+ reHasRegExpChars = RegExp(reRegExpChars.source);
- render: function() {
- return (
- React.createElement(Index, {category: ['alerts', 'tasks'],
- sort: "created:desc",
- hideAttributes: ['associatedResourceUri', 'associatedResourceCategory'],
- attributes: [
- {name: 'status', label: 'Status', filter: true},
- {name: 'name', label: 'Name'},
- {
- name: 'associatedResourceName',
- label: 'Resource',
- hasLink: true,
- render: function (item) {
- var href = IndexRouter.resourceHref(
- item.attributes.associatedResourceCategory,
- item.attributes.associatedResourceUri);
- var content;
- if (href) {
- content = (
- React.createElement(Link, {href: href},
- item.attributes.associatedResourceName
- )
- );
- } else {
- content = (
- React.createElement("a", null, item.attributes.associatedResourceName)
- );
- }
- return content;
- }
- },
- {name: 'created', label: 'Time'},
- {name: 'state', label: 'State', filter: true}
- ]}
- )
- );
- }
+ /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */
+ var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
- });
+ /** Used to match backslashes in property paths. */
+ var reEscapeChar = /\\(\\)?/g;
- module.exports = Activity;
+ /** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */
+ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+ /** Used to match `RegExp` flags from their coerced string values. */
+ var reFlags = /\w*$/;
-/***/ },
-/* 62 */
-/***/ function(module, exports, __webpack_require__) {
+ /** Used to detect hexadecimal string values. */
+ var reHasHexPrefix = /^0[xX]/;
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
-
- var React = __webpack_require__(48);
- var Resource = __webpack_require__(71);
-
- var ActivityResource = React.createClass({displayName: "ActivityResource",
+ /** Used to detect host constructors (Safari > 5). */
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
- render: function() {
- return (
- React.createElement(Resource, {category: ['alerts', 'tasks']})
- );
- }
+ /** Used to match latin-1 supplementary letters (excluding mathematical operators). */
+ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
- });
+ /** Used to ensure capturing order of template delimiters. */
+ var reNoMatch = /($^)/;
- module.exports = ActivityResource;
+ /** Used to match unescaped characters in compiled string literals. */
+ var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+ /** Used to match words to create compound words. */
+ var reWords = (function() {
+ var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]',
+ lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+';
-/***/ },
-/* 63 */
-/***/ function(module, exports, __webpack_require__) {
+ return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g');
+ }());
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ /** Used to detect and test for whitespace. */
+ var whitespace = (
+ // Basic whitespace characters.
+ ' \t\x0b\f\xa0\ufeff' +
- var React = __webpack_require__(48);
- var DashboardStore = __webpack_require__(76);
- var DashboardActions = __webpack_require__(73);
- var IndexActions = __webpack_require__(74);
- var IndexAggregate = __webpack_require__(84);
- var IndexRouter = __webpack_require__(60);
- var Router = __webpack_require__(2);
- var EditIcon = __webpack_require__(31);
- var Link = __webpack_require__(13);
+ // Line terminators.
+ '\n\r\u2028\u2029' +
- var Dashboard = React.createClass({displayName: "Dashboard",
+ // Unicode category "Zs" space separators.
+ '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
+ );
- _onChange: function () {
- this.setState(DashboardStore.getAll());
- },
+ /** Used to assign default `context` object properties. */
+ var contextProps = [
+ 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
+ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number',
+ 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document',
+ 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',
+ 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
+ 'window'
+ ];
- _onSearch: function (searchText, category) {
- var route = IndexRouter.categoryRoute(category);
- Router.transitionTo(route, {}, {'search': searchText});
- },
+ /** Used to make template sourceURLs easier to identify. */
+ var templateCounter = -1;
- getInitialState: function () {
- return DashboardStore.getAll();
- },
+ /** Used to identify `toStringTag` values of typed arrays. */
+ var typedArrayTags = {};
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
+ typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
+ typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
+ typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
+ typedArrayTags[uint32Tag] = true;
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
+ typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
+ typedArrayTags[dateTag] = typedArrayTags[errorTag] =
+ typedArrayTags[funcTag] = typedArrayTags[mapTag] =
+ typedArrayTags[numberTag] = typedArrayTags[objectTag] =
+ typedArrayTags[regexpTag] = typedArrayTags[setTag] =
+ typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
- componentWillMount: function () {
- DashboardActions.setup(this.props.configuration);
- },
+ /** Used to identify `toStringTag` values supported by `_.clone`. */
+ var cloneableTags = {};
+ cloneableTags[argsTag] = cloneableTags[arrayTag] =
+ cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
+ cloneableTags[dateTag] = cloneableTags[float32Tag] =
+ cloneableTags[float64Tag] = cloneableTags[int8Tag] =
+ cloneableTags[int16Tag] = cloneableTags[int32Tag] =
+ cloneableTags[numberTag] = cloneableTags[objectTag] =
+ cloneableTags[regexpTag] = cloneableTags[stringTag] =
+ cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
+ cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+ cloneableTags[errorTag] = cloneableTags[funcTag] =
+ cloneableTags[mapTag] = cloneableTags[setTag] =
+ cloneableTags[weakMapTag] = false;
- componentDidMount: function () {
- this.state.panels.forEach(function (panel) {
- IndexActions.getAggregates(panel.params, [panel.attribute.name], panel.name);
- });
- DashboardStore.addChangeListener(this._onChange);
- },
+ /** Used as an internal `_.debounce` options object by `_.throttle`. */
+ var debounceOptions = {
+ 'leading': false,
+ 'maxWait': 0,
+ 'trailing': false
+ };
- componentWillUnmount: function () {
- DashboardStore.removeChangeListener(this._onChange);
- },
+ /** Used to map latin-1 supplementary letters to basic latin letters. */
+ var deburredLetters = {
+ '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
+ '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
+ '\xc7': 'C', '\xe7': 'c',
+ '\xd0': 'D', '\xf0': 'd',
+ '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
+ '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
+ '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
+ '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
+ '\xd1': 'N', '\xf1': 'n',
+ '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
+ '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
+ '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
+ '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
+ '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
+ '\xc6': 'Ae', '\xe6': 'ae',
+ '\xde': 'Th', '\xfe': 'th',
+ '\xdf': 'ss'
+ };
- render: function () {
- var panels = this.state.panels.map(function (panel) {
- var href = IndexRouter.categoryHref(panel.params.category);
- var title = (
- React.createElement(Link, {href: href}, panel.name)
- );
+ /** Used to map characters to HTML entities. */
+ var htmlEscapes = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
+ };
- return (
- React.createElement("div", {key: panel.name, className: "dashboard__panel"},
- React.createElement(IndexAggregate, {title: title,
- category: panel.params.category,
- attribute: panel.attribute,
- search: panel.params.search,
- aggregateResult: panel.aggregateResult,
- onSearch: this._onSearch})
- )
- );
- }, this);
+ /** Used to map HTML entities to characters. */
+ var htmlUnescapes = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ ''': "'",
+ '`': '`'
+ };
- return (
- React.createElement("div", {className: "dashboard"},
- React.createElement("div", {className: "dashboard__panels"},
- panels
- ),
- React.createElement("div", {className: "dashboard__edit"},
- React.createElement(Link, {href: Router.makeHref("dashboard-edit")},
- React.createElement(EditIcon, {className: 'dashboard__edit-icon'})
- )
- )
- )
- );
- }
+ /** Used to determine if values are of the language type `Object`. */
+ var objectTypes = {
+ 'function': true,
+ 'object': true
+ };
- });
+ /** Used to escape characters for inclusion in compiled string literals. */
+ var stringEscapes = {
+ '\\': '\\',
+ "'": "'",
+ '\n': 'n',
+ '\r': 'r',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
- module.exports = Dashboard;
+ /** Detect free variable `exports`. */
+ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+ /** Detect free variable `module`. */
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
-/***/ },
-/* 64 */
-/***/ function(module, exports, __webpack_require__) {
+ /** Detect free variable `global` from Node.js. */
+ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ /** Detect free variable `self`. */
+ var freeSelf = objectTypes[typeof self] && self && self.Object && self;
- var React = __webpack_require__(48);
- var RouteHandler = __webpack_require__(82).RouteHandler;
- var DashboardStore = __webpack_require__(76);
- var DashboardActions = __webpack_require__(73);
- var Router = __webpack_require__(2);
- var Form = __webpack_require__(9);
- var IndexAggregate = __webpack_require__(84);
- var EditIcon = __webpack_require__(31);
- var RemoveIcon = __webpack_require__(29);
- var Link = __webpack_require__(13);
-
- var DashboardEdit = React.createClass({displayName: "DashboardEdit",
-
- _onChange: function() {
- this.setState(DashboardStore.getAll());
- },
+ /** Detect free variable `window`. */
+ var freeWindow = objectTypes[typeof window] && window && window.Object && window;
- _onOk: function (event) {
- event.preventDefault();
- DashboardActions.commitChanges();
- Router.transitionTo('dashboard');
- },
+ /** Detect the popular CommonJS extension `module.exports`. */
+ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
- _onCancel: function (event) {
- event.preventDefault();
- DashboardActions.abandonChanges();
- Router.transitionTo('dashboard');
- },
+ /**
+ * Used as a reference to the global object.
+ *
+ * The `this` value is used if it is the global object to avoid Greasemonkey's
+ * restricted `window` object, otherwise the `window` object is used.
+ */
+ var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
- _onRemove: function (panel) {
- DashboardActions.removePanel(panel);
- },
+ /**
+ * The base implementation of `compareAscending` which compares values and
+ * sorts them in ascending order without guaranteeing a stable sort.
+ *
+ * @private
+ * @param {*} value The value to compare to `other`.
+ * @param {*} other The value to compare to `value`.
+ * @returns {number} Returns the sort order indicator for `value`.
+ */
+ function baseCompareAscending(value, other) {
+ if (value !== other) {
+ var valIsReflexive = value === value,
+ othIsReflexive = other === other;
- _onDragStart: function(event) {
- this._dragged = event.currentTarget;
- event.dataTransfer.effectAllowed = 'move';
- // Firefox requires calling dataTransfer.setData
- // for the drag to properly work
- event.dataTransfer.setData("text/html", event.currentTarget);
- var rect = this._dragged.getBoundingClientRect();
- this._placeholder = document.createElement("li");
- this._placeholder.className =
- "dashboard-edit__panel dashboard-edit__panel--placeholder list-item box";
- this._placeholder.style.width = '' + (rect.right - rect.left) + 'px';
- this._placeholder.style.height = '' + (rect.bottom - rect.top) + 'px';
- },
+ if (value > other || !valIsReflexive || (value === undefined && othIsReflexive)) {
+ return 1;
+ }
+ if (value < other || !othIsReflexive || (other === undefined && valIsReflexive)) {
+ return -1;
+ }
+ }
+ return 0;
+ }
- _onDragEnd: function() {
- this._dragged.style.display = "inline-block";
- this._dragged.parentNode.removeChild(this._placeholder);
- this._placeholder = null;
+ /**
+ * The base implementation of `_.findIndex` and `_.findLastIndex` without
+ * support for callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseFindIndex(array, predicate, fromRight) {
+ var length = array.length,
+ index = fromRight ? length : -1;
- // Update state
- var pendingPanels = this.state.pendingPanels.slice(0);
- var from = Number(this._dragged.dataset.index);
- var to = Number(this._over.dataset.index);
- if (from < to) {
- to -= 1;
+ while ((fromRight ? index-- : ++index < length)) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
}
- pendingPanels.splice(to, 0, pendingPanels.splice(from, 1)[0]);
- DashboardActions.orderPanels(pendingPanels);
- },
+ return -1;
+ }
- _onDragOver: function(event) {
- event.preventDefault();
- this._dragged.style.display = "none";
- if (event.target.className ===
- "dashboard-edit__panel dashboard-edit__panel--placeholder list-item box") {
- return;
+ /**
+ * The base implementation of `_.indexOf` without support for binary searches.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseIndexOf(array, value, fromIndex) {
+ if (value !== value) {
+ return indexOfNaN(array, fromIndex);
}
- this._over = event.target;
- event.target.parentNode.insertBefore(this._placeholder, event.target);
- },
-
- getInitialState: function() {
- return DashboardStore.getAll();
- },
+ var index = fromIndex - 1,
+ length = array.length;
- componentDidMount: function() {
- DashboardActions.startChanging();
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
- DashboardStore.addChangeListener(this._onChange);
- },
-
- componentWillUnmount: function() {
- DashboardStore.removeChangeListener(this._onChange);
- },
-
- render: function() {
- var removeHandler = this._onRemove;
- var onDragStart = this._onDragStart;
- var onDragEnd = this._onDragEnd;
+ /**
+ * The base implementation of `_.isFunction` without support for environments
+ * with incorrect `typeof` results.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ */
+ function baseIsFunction(value) {
+ // Avoid a Chakra JIT bug in compatibility modes of IE 11.
+ // See https://github.com/jashkenas/underscore/issues/1621 for more details.
+ return typeof value == 'function' || false;
+ }
- var panels = [];
- if (this.state.pendingPanels) {
- panels = this.state.pendingPanels.map(function (panel, index) {
- return (
- React.createElement("li", {key: panel.name, "data-index": index,
- className: "dashboard-edit__panel list-item box",
- draggable: "true", onDragEnd: onDragEnd, onDragStart: onDragStart},
- React.createElement("div", {className: "dashboard-edit__panel-controls"},
- React.createElement(Link, {href: Router.makeHref('dashboard-panel-edit', {index: index}),
- className: "dashboard-edit__panel-edit"},
- React.createElement(EditIcon, {className: 'dashboard-edit__panel-edit-icon'})
- ),
- React.createElement("div", {className: "dashboard-edit__panel-remove",
- onClick: removeHandler.bind(null, panel)},
- React.createElement(RemoveIcon, {className: 'dashboard-edit__panel-remove-icon'})
- )
- ),
- React.createElement(IndexAggregate, {title: panel.name, params: panel.params,
- attribute: panel.attribute, aggregateResult: panel.aggregateResult})
- )
- );
- });
+ /**
+ * Converts `value` to a string if it is not one. An empty string is returned
+ * for `null` or `undefined` values.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {string} Returns the string.
+ */
+ function baseToString(value) {
+ if (typeof value == 'string') {
+ return value;
}
-
- var buttons = (
- React.createElement("div", null,
- React.createElement("button", {onClick: this._onOk, className: 'primary'}, "OK"),
- React.createElement("button", {onClick: this._onCancel}, "Cancel")
- )
- );
-
- return (
- React.createElement(Form, {action: 'Edit', resource: 'Dashboard', buttons: buttons},
- React.createElement("div", {className: "dashboard-edit"},
- React.createElement(Link, {href: Router.makeHref('dashboard-panel-add'),
- className: "dashboard-edit__add-panel"}, "+ Add panel"),
- React.createElement("ol", {className: "dashboard-edit__panels list-inline",
- onDragOver: this._onDragOver},
- panels
- ),
- React.createElement(RouteHandler, null)
- )
- )
- );
+ return value == null ? '' : (value + '');
}
- });
-
- module.exports = DashboardEdit;
-
-
-/***/ },
-/* 65 */
-/***/ function(module, exports, __webpack_require__) {
+ /**
+ * Used by `_.max` and `_.min` as the default callback for string values.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the code unit of the first character of the string.
+ */
+ function charAtCallback(string) {
+ return string.charCodeAt(0);
+ }
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ /**
+ * Used by `_.trim` and `_.trimLeft` to get the index of the first character
+ * of `string` that is not found in `chars`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @param {string} chars The characters to find.
+ * @returns {number} Returns the index of the first character not found in `chars`.
+ */
+ function charsLeftIndex(string, chars) {
+ var index = -1,
+ length = string.length;
- var React = __webpack_require__(48);
- var DashboardStore = __webpack_require__(76);
- var DashboardActions = __webpack_require__(73);
- var Router = __webpack_require__(2);
- var Form = __webpack_require__(9);
- var IndexAggregate = __webpack_require__(84);
+ while (++index < length && chars.indexOf(string.charAt(index)) > -1) {}
+ return index;
+ }
- var DashboardPanelAdd = React.createClass({displayName: "DashboardPanelAdd",
+ /**
+ * Used by `_.trim` and `_.trimRight` to get the index of the last character
+ * of `string` that is not found in `chars`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @param {string} chars The characters to find.
+ * @returns {number} Returns the index of the last character not found in `chars`.
+ */
+ function charsRightIndex(string, chars) {
+ var index = string.length;
- _onChange: function() {
- this.setState({dashboard: DashboardStore.getAll()});
- },
+ while (index-- && chars.indexOf(string.charAt(index)) > -1) {}
+ return index;
+ }
- _onClick: function (index) {
- this.setState({selectedIndex: index});
- },
+ /**
+ * Used by `_.sortBy` to compare transformed elements of a collection and stable
+ * sort them in ascending order.
+ *
+ * @private
+ * @param {Object} object The object to compare to `other`.
+ * @param {Object} other The object to compare to `object`.
+ * @returns {number} Returns the sort order indicator for `object`.
+ */
+ function compareAscending(object, other) {
+ return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index);
+ }
- _onAdd: function (event) {
- event.preventDefault();
- DashboardActions.addPanel(
- this.state.dashboard.availablePanels[this.state.selectedIndex]);
- Router.transitionTo('dashboard-edit');
- },
+ /**
+ * Used by `_.sortByOrder` to compare multiple properties of each element
+ * in a collection and stable sort them in the following order:
+ *
+ * If `orders` is unspecified, sort in ascending order for all properties.
+ * Otherwise, for each property, sort in ascending order if its corresponding value in
+ * orders is true, and descending order if false.
+ *
+ * @private
+ * @param {Object} object The object to compare to `other`.
+ * @param {Object} other The object to compare to `object`.
+ * @param {boolean[]} orders The order to sort by for each property.
+ * @returns {number} Returns the sort order indicator for `object`.
+ */
+ function compareMultiple(object, other, orders) {
+ var index = -1,
+ objCriteria = object.criteria,
+ othCriteria = other.criteria,
+ length = objCriteria.length,
+ ordersLength = orders.length;
- _onAddPlus: function (event) {
- event.preventDefault();
- DashboardActions.addPanel(
- this.state.dashboard.availablePanels[this.state.selectedIndex]);
- },
+ while (++index < length) {
+ var result = baseCompareAscending(objCriteria[index], othCriteria[index]);
+ if (result) {
+ if (index >= ordersLength) {
+ return result;
+ }
+ return result * (orders[index] ? 1 : -1);
+ }
+ }
+ // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+ // that causes it, under certain circumstances, to provide the same value for
+ // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
+ // for more details.
+ //
+ // This also ensures a stable sort in V8 and other engines.
+ // See https://code.google.com/p/v8/issues/detail?id=90 for more details.
+ return object.index - other.index;
+ }
- _onCancel: function (event) {
- event.preventDefault();
- Router.transitionTo('dashboard-edit');
- },
+ /**
+ * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
+ *
+ * @private
+ * @param {string} letter The matched letter to deburr.
+ * @returns {string} Returns the deburred letter.
+ */
+ function deburrLetter(letter) {
+ return deburredLetters[letter];
+ }
- getInitialState: function() {
- return {selectedIndex: 0, dashboard: DashboardStore.getAll()};
- },
+ /**
+ * Used by `_.escape` to convert characters to HTML entities.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeHtmlChar(chr) {
+ return htmlEscapes[chr];
+ }
- componentDidMount: function() {
- DashboardStore.addChangeListener(this._onChange);
- },
+ /**
+ * Used by `_.template` to escape characters for inclusion in compiled
+ * string literals.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeStringChar(chr) {
+ return '\\' + stringEscapes[chr];
+ }
- componentWillUnmount: function() {
- DashboardStore.removeChangeListener(this._onChange);
- },
+ /**
+ * Gets the index at which the first occurrence of `NaN` is found in `array`.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {number} fromIndex The index to search from.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched `NaN`, else `-1`.
+ */
+ function indexOfNaN(array, fromIndex, fromRight) {
+ var length = array.length,
+ index = fromIndex + (fromRight ? 0 : -1);
- render: function() {
- var clickHandler = this._onClick;
- var selectedIndex = this.state.selectedIndex;
- var panels = this.state.dashboard.availablePanels.map(function (panel, index) {
- var classes = ["dashboard-panel-add__panel", "list-item", "box"];
- if (index === selectedIndex) {
- classes.push("dashboard-panel-add__panel--selected");
+ while ((fromRight ? index-- : ++index < length)) {
+ var other = array[index];
+ if (other !== other) {
+ return index;
}
- return (
- React.createElement("li", {key: panel.name, className: classes.join(' '),
- onClick: clickHandler.bind(null, index)},
- React.createElement(IndexAggregate, {title: panel.name, params: panel.params,
- attribute: panel.attribute, aggregateResult: panel.aggregateResult})
- )
- );
- });
-
- var buttons = (
- React.createElement("div", null,
- React.createElement("button", {onClick: this._onAdd, className: 'primary'}, "Add"),
- React.createElement("button", {onClick: this._onAddPlus}, "Add +"),
- React.createElement("button", {onClick: this._onCancel}, "Cancel")
- )
- );
-
- return (
- React.createElement(Form, {action: 'Add Panel', resource: 'Dashboard', onSubmit: this._onSubmit,
- buttons: buttons},
- React.createElement("div", {className: "dashboard-panel-add"},
- React.createElement("ol", {className: "dashboard-panel-add__panels list-inline"},
- panels
- )
- )
- )
- );
+ }
+ return -1;
}
- });
+ /**
+ * Checks if `value` is object-like.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ */
+ function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+ }
- module.exports = DashboardPanelAdd;
+ /**
+ * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a
+ * character code is whitespace.
+ *
+ * @private
+ * @param {number} charCode The character code to inspect.
+ * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`.
+ */
+ function isSpace(charCode) {
+ return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 ||
+ (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279)));
+ }
+ /**
+ * Replaces all `placeholder` elements in `array` with an internal placeholder
+ * and returns an array of their indexes.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {*} placeholder The placeholder to replace.
+ * @returns {Array} Returns the new array of placeholder indexes.
+ */
+ function replaceHolders(array, placeholder) {
+ var index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
-/***/ },
-/* 66 */
-/***/ function(module, exports, __webpack_require__) {
+ while (++index < length) {
+ if (array[index] === placeholder) {
+ array[index] = PLACEHOLDER;
+ result[++resIndex] = index;
+ }
+ }
+ return result;
+ }
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ /**
+ * An implementation of `_.uniq` optimized for sorted arrays without support
+ * for callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The function invoked per iteration.
+ * @returns {Array} Returns the new duplicate-value-free array.
+ */
+ function sortedUniq(array, iteratee) {
+ var seen,
+ index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
- var React = __webpack_require__(48);
- var DashboardStore = __webpack_require__(76);
- var DashboardActions = __webpack_require__(73);
- var State = __webpack_require__(82).State;
- var Router = __webpack_require__(2);
- var Form = __webpack_require__(9);
- var DashboardPanelEditGuided = __webpack_require__(67);
- var DashboardPanelEditRaw = __webpack_require__(68);
- var IndexAggregate = __webpack_require__(84);
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value, index, array) : value;
- var DashboardPanelEdit = React.createClass({displayName: "DashboardPanelEdit",
+ if (!index || seen !== computed) {
+ seen = computed;
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
- mixins: [State],
+ /**
+ * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace
+ * character of `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the index of the first non-whitespace character.
+ */
+ function trimmedLeftIndex(string) {
+ var index = -1,
+ length = string.length;
- _onChange: function() {
- var data = DashboardStore.getAll();
- this.setState({pendingPanel: data.pendingPanel});
- },
+ while (++index < length && isSpace(string.charCodeAt(index))) {}
+ return index;
+ }
- _onOk: function (event) {
- event.preventDefault();
- var index = this.getParams().index;
- DashboardActions.updatePanel(index);
- Router.transitionTo('dashboard-edit');
- },
+ /**
+ * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace
+ * character of `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the index of the last non-whitespace character.
+ */
+ function trimmedRightIndex(string) {
+ var index = string.length;
- _onCancel: function (event) {
- event.preventDefault();
- Router.transitionTo('dashboard-edit');
- },
+ while (index-- && isSpace(string.charCodeAt(index))) {}
+ return index;
+ }
- _onChangeMode: function() {
- var mode = this.refs.mode.getDOMNode().value;
- this.setState({mode: mode});
- },
+ /**
+ * Used by `_.unescape` to convert HTML entities to characters.
+ *
+ * @private
+ * @param {string} chr The matched character to unescape.
+ * @returns {string} Returns the unescaped character.
+ */
+ function unescapeHtmlChar(chr) {
+ return htmlUnescapes[chr];
+ }
- getInitialState: function() {
- var data = DashboardStore.getAll();
- var index = this.getParams().index;
- return {
- mode: 'guided',
- panel: data.pendingPanels[index] || {},
- pendingPanel: null
- };
- },
+ /**
+ * Create a new pristine `lodash` function using the given `context` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Object} [context=root] The context object.
+ * @returns {Function} Returns a new `lodash` function.
+ * @example
+ *
+ * _.mixin({ 'foo': _.constant('foo') });
+ *
+ * var lodash = _.runInContext();
+ * lodash.mixin({ 'bar': lodash.constant('bar') });
+ *
+ * _.isFunction(_.foo);
+ * // => true
+ * _.isFunction(_.bar);
+ * // => false
+ *
+ * lodash.isFunction(lodash.foo);
+ * // => false
+ * lodash.isFunction(lodash.bar);
+ * // => true
+ *
+ * // using `context` to mock `Date#getTime` use in `_.now`
+ * var mock = _.runInContext({
+ * 'Date': function() {
+ * return { 'getTime': getTimeMock };
+ * }
+ * });
+ *
+ * // or creating a suped-up `defer` in Node.js
+ * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
+ */
+ function runInContext(context) {
+ // Avoid issues with some ES3 environments that attempt to use values, named
+ // after built-in constructors like `Object`, for the creation of literals.
+ // ES5 clears this up by stating that literals must use built-in constructors.
+ // See https://es5.github.io/#x11.1.5 for more details.
+ context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
- componentDidMount: function() {
- DashboardStore.addChangeListener(this._onChange);
- DashboardActions.editPanel(this.state.panel);
- },
+ /** Native constructor references. */
+ var Array = context.Array,
+ Date = context.Date,
+ Error = context.Error,
+ Function = context.Function,
+ Math = context.Math,
+ Number = context.Number,
+ Object = context.Object,
+ RegExp = context.RegExp,
+ String = context.String,
+ TypeError = context.TypeError;
- componentWillUnmount: function() {
- DashboardStore.removeChangeListener(this._onChange);
- },
+ /** Used for native method references. */
+ var arrayProto = Array.prototype,
+ objectProto = Object.prototype,
+ stringProto = String.prototype;
- render: function() {
- var config = {params: {}};
- if (this.state.pendingPanel) {
- config = this.state.pendingPanel.config;
- }
+ /** Used to detect DOM support. */
+ var document = (document = context.window) && document.document;
- var display = '';
- if (config.name) {
- display = (
- React.createElement(IndexAggregate, {title: config.name, params: config.params,
- attribute: config.attribute, aggregateResult: config.aggregateResult})
- );
- }
+ /** Used to resolve the decompiled source of functions. */
+ var fnToString = Function.prototype.toString;
- var buttons = (
- React.createElement("div", null,
- React.createElement("button", {onClick: this._onOk, className: 'primary'}, "OK"),
- React.createElement("button", {onClick: this._onCancel}, "Cancel")
- )
- );
+ /** Used to check objects for own properties. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
- var mode = this.state.mode;
- var guidedClasses = ["dashboard-panel-edit__guided"];
- var rawClasses = ["dashboard-panel-edit__raw"];
- if ('guided' === mode) {
- guidedClasses.push("dashboard-panel-edit__guided--active");
- } else {
- rawClasses.push("dashboard-panel-edit__raw--active");
- }
+ /** Used to generate unique IDs. */
+ var idCounter = 0;
- return (
- React.createElement(Form, {action: 'Edit', resource: config.name, buttons: buttons},
- React.createElement("div", {className: "dashboard-panel-edit"},
- React.createElement("div", {className: "dashboard-panel-edit__config"},
- React.createElement("select", {ref: "mode", className: "dashboard-panel-edit__mode-selector",
- onChange: this._onChangeMode, value: mode},
- React.createElement("option", null, "guided"),
- React.createElement("option", null, "raw")
- ),
+ /**
+ * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
+ * of values.
+ */
+ var objToString = objectProto.toString;
- React.createElement("div", {className: guidedClasses.join(' ')},
- React.createElement(DashboardPanelEditGuided, {pendingPanel: this.state.pendingPanel})
- ),
- React.createElement("div", {className: rawClasses.join(' ')},
- React.createElement(DashboardPanelEditRaw, {pendingPanel: this.state.pendingPanel})
- )
+ /** Used to restore the original `_` reference in `_.noConflict`. */
+ var oldDash = context._;
- ),
- React.createElement("div", {className: "dashboard-panel-edit__display"},
- display
- )
- )
- )
+ /** Used to detect if a method is native. */
+ var reIsNative = RegExp('^' +
+ escapeRegExp(objToString)
+ .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
- }
- });
+ /** Native method references. */
+ var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer,
+ bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice,
+ ceil = Math.ceil,
+ clearTimeout = context.clearTimeout,
+ floor = Math.floor,
+ getOwnPropertySymbols = isNative(getOwnPropertySymbols = Object.getOwnPropertySymbols) && getOwnPropertySymbols,
+ getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+ push = arrayProto.push,
+ preventExtensions = isNative(preventExtensions = Object.preventExtensions) && preventExtensions,
+ propertyIsEnumerable = objectProto.propertyIsEnumerable,
+ Set = isNative(Set = context.Set) && Set,
+ setTimeout = context.setTimeout,
+ splice = arrayProto.splice,
+ Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array,
+ WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap;
- module.exports = DashboardPanelEdit;
+ /** Used to clone array buffers. */
+ var Float64Array = (function() {
+ // Safari 5 errors when using an array buffer to initialize a typed array
+ // where the array buffer's `byteLength` is not a multiple of the typed
+ // array's `BYTES_PER_ELEMENT`.
+ try {
+ var func = isNative(func = context.Float64Array) && func,
+ result = new func(new ArrayBuffer(10), 0, 1) && func;
+ } catch(e) {}
+ return result;
+ }());
+ /** Used as `baseAssign`. */
+ var nativeAssign = (function() {
+ // Avoid `Object.assign` in Firefox 34-37 which have an early implementation
+ // with a now defunct try/catch behavior. See https://bugzilla.mozilla.org/show_bug.cgi?id=1103344
+ // for more details.
+ //
+ // Use `Object.preventExtensions` on a plain object instead of simply using
+ // `Object('x')` because Chrome and IE fail to throw an error when attempting
+ // to assign values to readonly indexes of strings.
+ var func = preventExtensions && isNative(func = Object.assign) && func;
+ try {
+ if (func) {
+ var object = preventExtensions({ '1': 0 });
+ object[0] = 1;
+ }
+ } catch(e) {
+ // Only attempt in strict mode.
+ try { func(object, 'xo'); } catch(e) {}
+ return !object[1] && func;
+ }
+ return false;
+ }());
-/***/ },
-/* 67 */
-/***/ function(module, exports, __webpack_require__) {
+ /* Native method references for those with the same name as other `lodash` methods. */
+ var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
+ nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
+ nativeIsFinite = context.isFinite,
+ nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
+ nativeMax = Math.max,
+ nativeMin = Math.min,
+ nativeNow = isNative(nativeNow = Date.now) && nativeNow,
+ nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite,
+ nativeParseInt = context.parseInt,
+ nativeRandom = Math.random;
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ /** Used as references for `-Infinity` and `Infinity`. */
+ var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY,
+ POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
- var React = __webpack_require__(48);
- var DashboardStore = __webpack_require__(76);
- var DashboardActions = __webpack_require__(73);
+ /** Used as references for the maximum length and index of an array. */
+ var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1,
+ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
+ HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
- var DashboardPanelEditGuided = React.createClass({displayName: "DashboardPanelEditGuided",
+ /** Used as the size, in bytes, of each `Float64Array` element. */
+ var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0;
- _onChange: function () {
- var panel = {
- name: this.refs.name.getDOMNode().value,
- params: {
- category: this.refs.category.getDOMNode().value,
- search: this.refs.search.getDOMNode().value
- },
- attribute: this.refs.attribute.getDOMNode().value,
- };
- DashboardActions.editPanel(panel);
- },
+ /**
+ * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
+ * of an array-like value.
+ */
+ var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
- getInitialState: function() {
- var data = DashboardStore.getAll();
- return({categories: data.categories});
- },
+ /** Used to store function metadata. */
+ var metaMap = WeakMap && new WeakMap;
- render: function() {
- var config = {params: {}};
- if (this.props.pendingPanel) {
- config = this.props.pendingPanel.config;
- }
-
- var options = this.state.categories.map(function (category) {
- return (
- React.createElement("option", null, category)
- );
- });
+ /** Used to lookup unminified function names. */
+ var realNames = {};
- var search = '';
- if (config.params.search) {
- search = config.params.search.fullText;
+ /**
+ * Creates a `lodash` object which wraps `value` to enable implicit chaining.
+ * Methods that operate on and return arrays, collections, and functions can
+ * be chained together. Methods that return a boolean or single value will
+ * automatically end the chain returning the unwrapped value. Explicit chaining
+ * may be enabled using `_.chain`. The execution of chained methods is lazy,
+ * that is, execution is deferred until `_#value` is implicitly or explicitly
+ * called.
+ *
+ * Lazy evaluation allows several methods to support shortcut fusion. Shortcut
+ * fusion is an optimization that merges iteratees to avoid creating intermediate
+ * arrays and reduce the number of iteratee executions.
+ *
+ * Chaining is supported in custom builds as long as the `_#value` method is
+ * directly or indirectly included in the build.
+ *
+ * In addition to lodash methods, wrappers have `Array` and `String` methods.
+ *
+ * The wrapper `Array` methods are:
+ * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`,
+ * `splice`, and `unshift`
+ *
+ * The wrapper `String` methods are:
+ * `replace` and `split`
+ *
+ * The wrapper methods that support shortcut fusion are:
+ * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,
+ * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`,
+ * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`,
+ * and `where`
+ *
+ * The chainable wrapper methods are:
+ * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`,
+ * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`,
+ * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`,
+ * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`,
+ * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`,
+ * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`,
+ * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`,
+ * `keysIn`, `map`, `mapValues`, `matches`, `matchesProperty`, `memoize`,
+ * `merge`, `mixin`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
+ * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`,
+ * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `reverse`,
+ * `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`,
+ * `spread`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`,
+ * `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, `transform`,
+ * `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, `where`,
+ * `without`, `wrap`, `xor`, `zip`, and `zipObject`
+ *
+ * The wrapper methods that are **not** chainable by default are:
+ * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`,
+ * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`,
+ * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`,
+ * `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, `isArray`,
+ * `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`
+ * `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`,
+ * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `isTypedArray`,
+ * `join`, `kebabCase`, `last`, `lastIndexOf`, `max`, `min`, `noConflict`,
+ * `noop`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`,
+ * `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, `shift`, `size`,
+ * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, `startsWith`,
+ * `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, `unescape`,
+ * `uniqueId`, `value`, and `words`
+ *
+ * The wrapper method `sample` will return a wrapped value when `n` is provided,
+ * otherwise an unwrapped value is returned.
+ *
+ * @name _
+ * @constructor
+ * @category Chain
+ * @param {*} value The value to wrap in a `lodash` instance.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var wrapped = _([1, 2, 3]);
+ *
+ * // returns an unwrapped value
+ * wrapped.reduce(function(total, n) {
+ * return total + n;
+ * });
+ * // => 6
+ *
+ * // returns a wrapped value
+ * var squares = wrapped.map(function(n) {
+ * return n * n;
+ * });
+ *
+ * _.isArray(squares);
+ * // => false
+ *
+ * _.isArray(squares.value());
+ * // => true
+ */
+ function lodash(value) {
+ if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
+ if (value instanceof LodashWrapper) {
+ return value;
+ }
+ if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {
+ return wrapperClone(value);
+ }
+ }
+ return new LodashWrapper(value);
}
- return (
- React.createElement("fieldset", {className: 'dashboard-panel-edit-guided form__fields'},
- React.createElement("div", {className: 'form__field'},
- React.createElement("label", {htmlFor: 'name'}, "Name"),
- React.createElement("input", {ref: 'name', id: 'name', value: config.name,
- onChange: this._onChange})
- ),
- React.createElement("div", {className: 'form__field'},
- React.createElement("label", {htmlFor: 'category'}, "Category"),
- React.createElement("select", {ref: 'category', id: 'category',
- value: config.params.category,
- onChange: this._onChange},
- options
- )
- ),
- React.createElement("div", {className: 'form__field'},
- React.createElement("label", {htmlFor: 'search'}, "Filter"),
- React.createElement("textarea", {ref: 'search', id: 'search', value: search,
- onChange: this._onChange})
- ),
- React.createElement("div", {className: 'form__field'},
- React.createElement("label", {htmlFor: 'attribute'}, "Attribute"),
- React.createElement("select", {ref: 'attribute', id: 'attribute',
- onChange: this._onChange},
- React.createElement("option", null, config.attribute)
- )
- )
- )
- );
- }
-
- });
-
- module.exports = DashboardPanelEditGuided;
+ /**
+ * The function whose prototype all chaining wrappers inherit from.
+ *
+ * @private
+ */
+ function baseLodash() {
+ // No operation performed.
+ }
+ /**
+ * The base constructor for creating `lodash` wrapper objects.
+ *
+ * @private
+ * @param {*} value The value to wrap.
+ * @param {boolean} [chainAll] Enable chaining for all wrapper methods.
+ * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value.
+ */
+ function LodashWrapper(value, chainAll, actions) {
+ this.__wrapped__ = value;
+ this.__actions__ = actions || [];
+ this.__chain__ = !!chainAll;
+ }
-/***/ },
-/* 68 */
-/***/ function(module, exports, __webpack_require__) {
+ /**
+ * An object environment feature flags.
+ *
+ * @static
+ * @memberOf _
+ * @type Object
+ */
+ var support = lodash.support = {};
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ (function(x) {
+ var Ctor = function() { this.x = x; },
+ args = arguments,
+ object = { '0': x, 'length': x },
+ props = [];
- var React = __webpack_require__(48);
- var DashboardActions = __webpack_require__(73);
+ Ctor.prototype = { 'valueOf': x, 'y': x };
+ for (var key in new Ctor) { props.push(key); }
- var DashboardPanelEditRaw = React.createClass({displayName: "DashboardPanelEditRaw",
+ /**
+ * Detect if functions can be decompiled by `Function#toString`
+ * (all but Firefox OS certified apps, older Opera mobile browsers, and
+ * the PlayStation 3; forced `false` for Windows 8 apps).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.funcDecomp = /\bthis\b/.test(function() { return this; });
- _onChange: function (event) {
- var text = event.target.value;
- DashboardActions.editPanel(text);
- },
+ /**
+ * Detect if `Function#name` is supported (all but IE).
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ support.funcNames = typeof Function.name == 'string';
- render: function() {
- var text = '';
- var error = '';
- if (this.props.pendingPanel) {
- text = this.props.pendingPanel.text;
- error = this.props.pendingPanel.error;
- }
- return (
- React.createElement("div", {className: "dashboard-panel-edit-raw"},
- React.createElement("textarea", {onChange: this._onChange,
- value: text}),
- React.createElement("div", {className: "dashboard-panel-edit-raw__error"},
- error
- )
- )
- );
- }
+ /**
+ * Detect if the DOM is supported.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ try {
+ support.dom = document.createDocumentFragment().nodeType === 11;
+ } catch(e) {
+ support.dom = false;
+ }
- });
+ /**
+ * Detect if `arguments` object indexes are non-enumerable.
+ *
+ * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object
+ * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat
+ * `arguments` object indexes as non-enumerable and fail `hasOwnProperty`
+ * checks for indexes that exceed the number of function parameters and
+ * whose associated argument values are `0`.
+ *
+ * @memberOf _.support
+ * @type boolean
+ */
+ try {
+ support.nonEnumArgs = !propertyIsEnumerable.call(args, 1);
+ } catch(e) {
+ support.nonEnumArgs = true;
+ }
+ }(1, 0));
- module.exports = DashboardPanelEditRaw;
+ /**
+ * By default, the template delimiters used by lodash are like those in
+ * embedded Ruby (ERB). Change the following template settings to use
+ * alternative delimiters.
+ *
+ * @static
+ * @memberOf _
+ * @type Object
+ */
+ lodash.templateSettings = {
+ /**
+ * Used to detect `data` property values to be HTML-escaped.
+ *
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'escape': reEscape,
-/***/ },
-/* 69 */
-/***/ function(module, exports, __webpack_require__) {
+ /**
+ * Used to detect code to be evaluated.
+ *
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'evaluate': reEvaluate,
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ /**
+ * Used to detect `data` property values to inject.
+ *
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'interpolate': reInterpolate,
- var React = __webpack_require__(48);
- var NavStore = __webpack_require__(85);
- var Router = __webpack_require__(2);
- var IndexRouter = __webpack_require__(60);
- var IndexStore = __webpack_require__(77);
- var IndexActions = __webpack_require__(74);
- var IndexHeader = __webpack_require__(86);
- var IndexResults = __webpack_require__(87);
- var IndexFilter = __webpack_require__(88);
- var IndexResource = __webpack_require__(89);
- var Search = __webpack_require__(90);
+ /**
+ * Used to reference the data object in the template text.
+ *
+ * @memberOf _.templateSettings
+ * @type string
+ */
+ 'variable': '',
- var CLASS_ROOT = 'index';
-
- var Index = React.createClass({displayName: "Index",
+ /**
+ * Used to import variables into the compiled template.
+ *
+ * @memberOf _.templateSettings
+ * @type Object
+ */
+ 'imports': {
- contextTypes: {
- router: React.PropTypes.func.isRequired
- },
+ /**
+ * A reference to the `lodash` function.
+ *
+ * @memberOf _.templateSettings.imports
+ * @type Function
+ */
+ '_': lodash
+ }
+ };
- _mobileScroll: function () {
- // if we are narrow, scroll down to hide app header above
- var indexElement = this.refs.index.getDOMNode();
- var rect = indexElement.getBoundingClientRect();
- if (window.innerWidth < 720 && rect.top > 0) {
- setTimeout(function () {
- window.scrollTo(0, rect.top);
- }, 100);
+ /**
+ * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
+ *
+ * @private
+ * @param {*} value The value to wrap.
+ */
+ function LazyWrapper(value) {
+ this.__wrapped__ = value;
+ this.__actions__ = null;
+ this.__dir__ = 1;
+ this.__dropCount__ = 0;
+ this.__filtered__ = false;
+ this.__iteratees__ = null;
+ this.__takeCount__ = POSITIVE_INFINITY;
+ this.__views__ = null;
}
- },
-
- _search: function (searchText, resourceUri) {
- var index = IndexStore.getAll();
- IndexActions.search(Search.create(searchText || ''), resourceUri, index);
- },
- _onIndexChange: function () {
- var index = IndexStore.getAll();
- this.setState({index: index});
- },
+ /**
+ * Creates a clone of the lazy wrapper object.
+ *
+ * @private
+ * @name clone
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the cloned `LazyWrapper` object.
+ */
+ function lazyClone() {
+ var actions = this.__actions__,
+ iteratees = this.__iteratees__,
+ views = this.__views__,
+ result = new LazyWrapper(this.__wrapped__);
- _onNavChange: function () {
- // TODO: Does Index know too much about route configuration here?
- var resourceActive = Router.isActive(this.state.resourceRoute);
- var resourceUri = null;
- if (resourceActive) {
- resourceUri = Router.param('splat');
- this.setState({
- resourceActive: resourceActive,
- resourceUri: resourceUri,
- filterActive: false});
- } else {
- this.setState({resourceActive: false, resourceUri: null});
+ result.__actions__ = actions ? arrayCopy(actions) : null;
+ result.__dir__ = this.__dir__;
+ result.__filtered__ = this.__filtered__;
+ result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null;
+ result.__takeCount__ = this.__takeCount__;
+ result.__views__ = views ? arrayCopy(views) : null;
+ return result;
}
- // delay to avoid nested dispatches
- clearTimeout(this._navTimer);
- var searchText = Router.queryParam('search') || '';
- if (searchText !== this.state.index.params.search.fullText) {
- this._navTimer = setTimeout(this._search.
- bind(null, searchText, resourceUri), 10);
+ /**
+ * Reverses the direction of lazy iteration.
+ *
+ * @private
+ * @name reverse
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the new reversed `LazyWrapper` object.
+ */
+ function lazyReverse() {
+ if (this.__filtered__) {
+ var result = new LazyWrapper(this);
+ result.__dir__ = -1;
+ result.__filtered__ = true;
+ } else {
+ result = this.clone();
+ result.__dir__ *= -1;
+ }
+ return result;
}
- this._mobileScroll();
- },
-
- _onSearch: function (searchText) {
- Router.replaceQueryParam('search', searchText);
- // causes: _onNavChange -> _search -> _onIndexChange
- },
-
- _onOpenFilter: function () {
- this.setState({filterActive: true, resourceActive: false});
- },
-
- _onCloseFilter: function () {
- this.setState({filterActive: false});
- },
-
- _onCloseResource: function () {
- var categoryRoute = IndexRouter.categoryRoute(this.props.category);
- Router.transitionTo(categoryRoute, {}, Router.queryParams());
- },
-
- getInitialState: function () {
- this._navTimer = null;
- var resourceRoute = IndexRouter.resourceRoute(this.props.category);
+ /**
+ * Extracts the unwrapped value from its lazy wrapper.
+ *
+ * @private
+ * @name value
+ * @memberOf LazyWrapper
+ * @returns {*} Returns the unwrapped value.
+ */
+ function lazyValue() {
+ var array = this.__wrapped__.value();
+ if (!isArray(array)) {
+ return baseWrapperValue(array, this.__actions__);
+ }
+ var dir = this.__dir__,
+ isRight = dir < 0,
+ view = getView(0, array.length, this.__views__),
+ start = view.start,
+ end = view.end,
+ length = end - start,
+ index = isRight ? end : (start - 1),
+ takeCount = nativeMin(length, this.__takeCount__),
+ iteratees = this.__iteratees__,
+ iterLength = iteratees ? iteratees.length : 0,
+ resIndex = 0,
+ result = [];
- return {
- filterActive: false,
- resourceRoute: resourceRoute,
- resourceActive: Router.isActive(resourceRoute),
- resourceUri: Router.param('splat'),
- index: IndexStore.getAll()
- };
- },
+ outer:
+ while (length-- && resIndex < takeCount) {
+ index += dir;
- componentWillMount: function () {
- IndexActions.setContext({
- category: this.props.category,
- view: this.props.view,
- searchMode: this.props.searchMode || 'filters',
- attributes: this.props.attributes
- });
- },
+ var iterIndex = -1,
+ value = array[index];
- componentDidMount: function () {
- // get data
- this._search(Router.queryParam('search'), this.state.resourceUri);
+ while (++iterIndex < iterLength) {
+ var data = iteratees[iterIndex],
+ iteratee = data.iteratee,
+ type = data.type;
- IndexStore.addChangeListener(this._onIndexChange);
- NavStore.addChangeListener(this._onNavChange);
+ if (type == LAZY_DROP_WHILE_FLAG) {
+ if (data.done && (isRight ? (index > data.index) : (index < data.index))) {
+ data.count = 0;
+ data.done = false;
+ }
+ data.index = index;
+ if (!data.done) {
+ var limit = data.limit;
+ if (!(data.done = limit > -1 ? (data.count++ >= limit) : !iteratee(value))) {
+ continue outer;
+ }
+ }
+ } else {
+ var computed = iteratee(value);
+ if (type == LAZY_MAP_FLAG) {
+ value = computed;
+ } else if (!computed) {
+ if (type == LAZY_FILTER_FLAG) {
+ continue outer;
+ } else {
+ break outer;
+ }
+ }
+ }
+ }
+ result[resIndex++] = value;
+ }
+ return result;
+ }
- this._mobileScroll();
- },
+ /**
+ * Creates a cache object to store key/value pairs.
+ *
+ * @private
+ * @static
+ * @name Cache
+ * @memberOf _.memoize
+ */
+ function MapCache() {
+ this.__data__ = {};
+ }
- componentWillUnmount: function () {
- clearTimeout(this._navTimer);
- IndexStore.removeChangeListener(this._onIndexChange);
- NavStore.removeChangeListener(this._onNavChange);
- },
+ /**
+ * Removes `key` and its value from the cache.
+ *
+ * @private
+ * @name delete
+ * @memberOf _.memoize.Cache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`.
+ */
+ function mapDelete(key) {
+ return this.has(key) && delete this.__data__[key];
+ }
- render: function () {
- var classes = [CLASS_ROOT];
- var filterClasses = [CLASS_ROOT + "__filter"];
- var resourceClasses = [CLASS_ROOT + "__resource"];
+ /**
+ * Gets the cached value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf _.memoize.Cache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the cached value.
+ */
+ function mapGet(key) {
+ return key == '__proto__' ? undefined : this.__data__[key];
+ }
- if (this.state.filterActive) {
- classes.push(CLASS_ROOT + "--shared");
- filterClasses.push(CLASS_ROOT + "__filter--active");
+ /**
+ * Checks if a cached value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf _.memoize.Cache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function mapHas(key) {
+ return key != '__proto__' && hasOwnProperty.call(this.__data__, key);
}
- if (this.state.resourceActive) {
- classes.push(CLASS_ROOT + "--shared");
- resourceClasses.push(CLASS_ROOT + "__resource--active");
+ /**
+ * Sets `value` to `key` of the cache.
+ *
+ * @private
+ * @name set
+ * @memberOf _.memoize.Cache
+ * @param {string} key The key of the value to cache.
+ * @param {*} value The value to cache.
+ * @returns {Object} Returns the cache object.
+ */
+ function mapSet(key, value) {
+ if (key != '__proto__') {
+ this.__data__[key] = value;
+ }
+ return this;
}
- return (
- React.createElement("div", {ref: "index", className: classes.join(' ')},
- React.createElement(IndexFilter, {className: filterClasses.join(' '),
- category: this.props.category,
- search: this.state.index.params.search,
- attributes: this.state.index.attributes,
- active: this.state.filterActive,
- onSearch: this._onSearch,
- onClose: this._onCloseFilter}),
-
- React.createElement("div", {className: CLASS_ROOT + "__content"},
- React.createElement(IndexHeader, {className: CLASS_ROOT + "__header",
- category: this.props.category,
- index: this.state.index,
- title: IndexRouter.categoryLabel(this.props.category),
- onSearch: this._onSearch,
- onOpenFilter: this._onOpenFilter,
- filterActive: this.state.filterActive,
- addRoute: this.props.addRoute}),
- React.createElement(IndexResults, {className: CLASS_ROOT + "__results",
- category: this.props.category,
- index: this.state.index,
- resourceActive: this.state.resourceActive,
- onSearch: this._onSearch})
- ),
+ /**
+ *
+ * Creates a cache object to store unique values.
+ *
+ * @private
+ * @param {Array} [values] The values to cache.
+ */
+ function SetCache(values) {
+ var length = values ? values.length : 0;
- React.createElement(IndexResource, {className: resourceClasses.join(' '),
- category: this.props.category,
- index: this.state.index,
- uri: this.state.resourceUri,
- onClose: this._onCloseResource})
- )
- );
- }
+ this.data = { 'hash': nativeCreate(null), 'set': new Set };
+ while (length--) {
+ this.push(values[length]);
+ }
+ }
- });
+ /**
+ * Checks if `value` is in `cache` mimicking the return signature of
+ * `_.indexOf` by returning `0` if the value is found, else `-1`.
+ *
+ * @private
+ * @param {Object} cache The cache to search.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns `0` if `value` is found, else `-1`.
+ */
+ function cacheIndexOf(cache, value) {
+ var data = cache.data,
+ result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value];
- module.exports = Index;
+ return result ? 0 : -1;
+ }
+ /**
+ * Adds `value` to the cache.
+ *
+ * @private
+ * @name push
+ * @memberOf SetCache
+ * @param {*} value The value to cache.
+ */
+ function cachePush(value) {
+ var data = this.data;
+ if (typeof value == 'string' || isObject(value)) {
+ data.set.add(value);
+ } else {
+ data.hash[value] = true;
+ }
+ }
-/***/ },
-/* 70 */
-/***/ function(module, exports, __webpack_require__) {
+ /**
+ * Copies the values of `source` to `array`.
+ *
+ * @private
+ * @param {Array} source The array to copy values from.
+ * @param {Array} [array=[]] The array to copy values to.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayCopy(source, array) {
+ var index = -1,
+ length = source.length;
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ array || (array = Array(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+ }
- var React = __webpack_require__(48);
- var IndexStore = __webpack_require__(77);
- var IndexActions = __webpack_require__(74);
- var State = __webpack_require__(82).State;
- var Router = __webpack_require__(2);
- var IndexRouter = __webpack_require__(60);
- var Form = __webpack_require__(9);
+ /**
+ * A specialized version of `_.forEach` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array.length;
- var CLASS_ROOT = 'index-edit';
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
- var IndexEdit = React.createClass({displayName: "IndexEdit",
+ /**
+ * A specialized version of `_.forEachRight` for arrays without support for
+ * callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEachRight(array, iteratee) {
+ var length = array.length;
- mixins: [State],
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
- _onChange: function() {
- this.setState(IndexStore.getAll());
- },
+ /**
+ * A specialized version of `_.every` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ */
+ function arrayEvery(array, predicate) {
+ var index = -1,
+ length = array.length;
- _done: function () {
- var queryArgs = {};
- var searchText = this.state.params.search.fullText;
- if (searchText) {
- queryArgs.search = searchText;
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
}
- Router.transitionTo(IndexRouter.categoryRoute(this.getParams().category),
- {}, queryArgs);
- },
- _onOk: function (event) {
- event.preventDefault();
- IndexActions.commitChanges();
- this._done();
- },
+ /**
+ * A specialized version of `_.filter` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function arrayFilter(array, predicate) {
+ var index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
- _onCancel: function (event) {
- event.preventDefault();
- IndexActions.abandonChanges();
- this._done();
- },
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
- _onChangeView: function (view) {
- IndexActions.setView(view);
- },
+ /**
+ * A specialized version of `_.map` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array.length,
+ result = Array(length);
- _onChangeSearch: function (searchMode) {
- IndexActions.setSearchMode(searchMode);
- },
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
- _onAttributeToggleVisible: function (attribute) {
- attribute.visible = ! attribute.visible;
- IndexActions.updateAttribute(attribute);
- },
+ /**
+ * A specialized version of `_.max` for arrays without support for iteratees.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @returns {*} Returns the maximum value.
+ */
+ function arrayMax(array) {
+ var index = -1,
+ length = array.length,
+ result = NEGATIVE_INFINITY;
- _onAttributeToggleAggregate: function (attribute) {
- attribute.aggregate = ! attribute.aggregate;
- IndexActions.updateAttribute(attribute);
- },
+ while (++index < length) {
+ var value = array[index];
+ if (value > result) {
+ result = value;
+ }
+ }
+ return result;
+ }
- _onAttributeToggleFilter: function (attribute) {
- attribute.filter = ! attribute.filter;
- IndexActions.updateAttribute(attribute);
- },
+ /**
+ * A specialized version of `_.min` for arrays without support for iteratees.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @returns {*} Returns the minimum value.
+ */
+ function arrayMin(array) {
+ var index = -1,
+ length = array.length,
+ result = POSITIVE_INFINITY;
- _onDragStart: function(event) {
- this._dragged = event.currentTarget;
- event.dataTransfer.effectAllowed = 'move';
- // Firefox requires calling dataTransfer.setData
- // for the drag to properly work
- event.dataTransfer.setData("text/html", event.currentTarget);
- var rect = this._dragged.getBoundingClientRect();
- this._placeholder = document.createElement("li");
- this._placeholder.className =
- CLASS_ROOT + "__attribute " + CLASS_ROOT + "__attribute--placeholder list-item";
- this._placeholder.style.width = '' + (rect.right - rect.left) + 'px';
- this._placeholder.style.height = '' + (rect.bottom - rect.top) + 'px';
- },
+ while (++index < length) {
+ var value = array[index];
+ if (value < result) {
+ result = value;
+ }
+ }
+ return result;
+ }
- _onDragEnd: function() {
- this._dragged.style.display = "block";
- this._dragged.parentNode.removeChild(this._placeholder);
- this._placeholder = null;
+ /**
+ * A specialized version of `_.reduce` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initFromArray] Specify using the first element of `array`
+ * as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduce(array, iteratee, accumulator, initFromArray) {
+ var index = -1,
+ length = array.length;
- var from = Number(this._dragged.dataset.index);
- var to = Number(this._over.dataset.index);
- if (from < to) {
- to -= 1;
+ if (initFromArray && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
}
- IndexActions.moveAttribute(from, to);
- },
- _onDragOver: function(event) {
- event.preventDefault();
- this._dragged.style.display = "none";
- if (event.target.className ===
- CLASS_ROOT + "__attribute " + CLASS_ROOT + "__attribute--placeholder list-item") {
- return;
+ /**
+ * A specialized version of `_.reduceRight` for arrays without support for
+ * callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initFromArray] Specify using the last element of `array`
+ * as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
+ var length = array.length;
+ if (initFromArray && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
}
- this._over = event.target;
- event.target.parentNode.insertBefore(this._placeholder, event.target);
- },
-
- getInitialState: function() {
- return IndexStore.getAll();
- },
- /*componentWillMount: function () {
- IndexActions.setContext({
- category: this.getParams().category
- });
- },*/
+ /**
+ * A specialized version of `_.some` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function arraySome(array, predicate) {
+ var index = -1,
+ length = array.length;
- componentDidMount: function() {
- IndexStore.addChangeListener(this._onChange);
- IndexActions.startChanging();
- },
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
- componentWillUnmount: function() {
- IndexStore.removeChangeListener(this._onChange);
- },
-
- render: function() {
-
- var buttons = (
- React.createElement("div", null,
- React.createElement("button", {onClick: this._onOk, className: 'primary'}, "OK"),
- React.createElement("button", {onClick: this._onCancel}, "Cancel")
- )
- );
+ /**
+ * A specialized version of `_.sum` for arrays without support for iteratees.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @returns {number} Returns the sum.
+ */
+ function arraySum(array) {
+ var length = array.length,
+ result = 0;
- var view = '';
- var searchMode = '';
- var attributes = [];
- if (this.state.pendingChanges) {
- view = this.state.pendingChanges.view;
- searchMode = this.state.pendingChanges.searchMode;
- attributes = this.state.pendingChanges.attributes;
+ while (length--) {
+ result += +array[length] || 0;
+ }
+ return result;
}
- /**var attributes = attributes.map(function (attribute, index) {
- var id = 'a-' + index;
- return (
-
-
-
- {attribute.label}
-
-
-
-
-
- );
- }, this);**/
-
- return (
- React.createElement(Form, {action: 'Edit',
- resource: IndexRouter.categoryLabel(this.getParams().category),
- buttons: buttons},
- React.createElement("div", {className: CLASS_ROOT},
- React.createElement("fieldset", {className: 'form__fields'},
- React.createElement("div", {className: 'form__field'},
- React.createElement("label", null, "View"),
- React.createElement("label", {className: 'radiobutton', htmlFor: 'view__table'},
- React.createElement("input", {id: "view__table", type: "radio", name: "view", value: "table",
- checked: 'table' === view,
- onChange: this._onChangeView.bind(null, 'table')}),
- "table"
- ),
- React.createElement("label", {className: 'radiobutton', htmlFor: 'view__tiles'},
- React.createElement("input", {id: "view__tiles", type: "radio", name: "view", value: "tiles",
- checked: 'tiles' === view,
- onChange: this._onChangeView.bind(null, 'tiles')}),
- "tiles"
- )
- ),
- React.createElement("div", {className: 'form__field'},
- React.createElement("label", null, "Search"),
- React.createElement("label", {className: 'radiobutton', htmlFor: 'search__filters'},
- React.createElement("input", {id: "search__filters", type: "radio", name: "searchMode", value: "filters",
- checked: 'filters' === searchMode,
- onChange: this._onChangeSearch.bind(null, 'filters')}),
- "filters"
- ),
- React.createElement("label", {className: 'radiobutton', htmlFor: 'search__facets'},
- React.createElement("input", {id: "search__facets", type: "radio", name: "searchMode", value: "facets",
- checked: 'facets' === searchMode,
- onChange: this._onChangeSearch.bind(null, 'facets')}),
- "facets"
- )
- ),
- React.createElement("div", {className: 'form__field'},
- React.createElement("label", null, "Attributes"),
- React.createElement("ol", {className: CLASS_ROOT + "__attributes list-block list-block--small",
- onDragOver: this._onDragOver},
- attributes
- )
- )
- )
- )
- )
- );
- }
-
- });
-
- module.exports = IndexEdit;
+ /**
+ * Used by `_.defaults` to customize its `_.assign` use.
+ *
+ * @private
+ * @param {*} objectValue The destination object property value.
+ * @param {*} sourceValue The source object property value.
+ * @returns {*} Returns the value to assign to the destination object.
+ */
+ function assignDefaults(objectValue, sourceValue) {
+ return objectValue === undefined ? sourceValue : objectValue;
+ }
+ /**
+ * Used by `_.template` to customize its `_.assign` use.
+ *
+ * **Note:** This function is like `assignDefaults` except that it ignores
+ * inherited property values when checking if a property is `undefined`.
+ *
+ * @private
+ * @param {*} objectValue The destination object property value.
+ * @param {*} sourceValue The source object property value.
+ * @param {string} key The key associated with the object and source values.
+ * @param {Object} object The destination object.
+ * @returns {*} Returns the value to assign to the destination object.
+ */
+ function assignOwnDefaults(objectValue, sourceValue, key, object) {
+ return (objectValue === undefined || !hasOwnProperty.call(object, key))
+ ? sourceValue
+ : objectValue;
+ }
-/***/ },
-/* 71 */
-/***/ function(module, exports, __webpack_require__) {
+ /**
+ * A specialized version of `_.assign` for customizing assigned values without
+ * support for argument juggling, multiple sources, and `this` binding `customizer`
+ * functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {Function} customizer The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ */
+ function assignWith(object, source, customizer) {
+ var props = keys(source);
+ push.apply(props, getSymbols(source));
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
+ var index = -1,
+ length = props.length;
- var React = __webpack_require__(48);
- var ResourceStore = __webpack_require__(78);
- var NavStore = __webpack_require__(85);
- var Router = __webpack_require__(2);
- var ResourceActions = __webpack_require__(75);
- var ResourceHeader = __webpack_require__(91);
- var ResourceActivity = __webpack_require__(92);
- var ResourceMap = __webpack_require__(93);
+ while (++index < length) {
+ var key = props[index],
+ value = object[key],
+ result = customizer(value, source[key], key, object, source);
- var CLASS_ROOT = 'resource';
+ if ((result === result ? (result !== value) : (value === value)) ||
+ (value === undefined && !(key in object))) {
+ object[key] = result;
+ }
+ }
+ return object;
+ }
- var Resource = React.createClass({displayName: "Resource",
+ /**
+ * The base implementation of `_.assign` without support for argument juggling,
+ * multiple sources, and `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+ var baseAssign = nativeAssign || function(object, source) {
+ return source == null
+ ? object
+ : baseCopy(source, getSymbols(source), baseCopy(source, keys(source), object));
+ };
- _onChange: function() {
- this.setState(ResourceStore.getAll());
- },
+ /**
+ * The base implementation of `_.at` without support for string collections
+ * and individual key arguments.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {number[]|string[]} props The property names or indexes of elements to pick.
+ * @returns {Array} Returns the new array of picked elements.
+ */
+ function baseAt(collection, props) {
+ var index = -1,
+ isNil = collection == null,
+ isArr = !isNil && isArrayLike(collection),
+ length = isArr && collection.length,
+ propsLength = props.length,
+ result = Array(propsLength);
- _onNavChange: function() {
- var uri = Router.param('splat');
- if (uri && uri !== this.state.uri) {
- // delay to avoid nested dispatches
- var category = this.props.category;
- clearTimeout(this._navTimer);
- this._navTimer = setTimeout(function () {
- ResourceActions.get(uri, category);
- }, 10);
+ while(++index < propsLength) {
+ var key = props[index];
+ if (isArr) {
+ result[index] = isIndex(key, length) ? collection[key] : undefined;
+ } else {
+ result[index] = isNil ? undefined : collection[key];
+ }
+ }
+ return result;
}
- },
- getInitialState: function() {
- return ResourceStore.getAll();
- },
+ /**
+ * Copies properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy properties from.
+ * @param {Array} props The property names to copy.
+ * @param {Object} [object={}] The object to copy properties to.
+ * @returns {Object} Returns `object`.
+ */
+ function baseCopy(source, props, object) {
+ object || (object = {});
- componentDidMount: function() {
- ResourceStore.addChangeListener(this._onChange);
- NavStore.addChangeListener(this._onNavChange);
- // get data
- var uri = Router.param('splat');
- ResourceActions.get(uri, this.props.category);
- },
+ var index = -1,
+ length = props.length;
- componentWillUnmount: function() {
- ResourceStore.removeChangeListener(this._onChange);
- NavStore.removeChangeListener(this._onNavChange);
- clearTimeout(this._navTimer);
- },
+ while (++index < length) {
+ var key = props[index];
+ object[key] = source[key];
+ }
+ return object;
+ }
- render: function() {
- var classes = [CLASS_ROOT];
- var response = this.state.response;
- if (! response) {
- classes.push(CLASS_ROOT + "--loading");
+ /**
+ * The base implementation of `_.callback` which supports specifying the
+ * number of arguments to provide to `func`.
+ *
+ * @private
+ * @param {*} [func=_.identity] The value to convert to a callback.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {number} [argCount] The number of arguments to provide to `func`.
+ * @returns {Function} Returns the callback.
+ */
+ function baseCallback(func, thisArg, argCount) {
+ var type = typeof func;
+ if (type == 'function') {
+ return thisArg === undefined
+ ? func
+ : bindCallback(func, thisArg, argCount);
+ }
+ if (func == null) {
+ return identity;
+ }
+ if (type == 'object') {
+ return baseMatches(func);
+ }
+ return thisArg === undefined
+ ? property(func)
+ : baseMatchesProperty(func, thisArg);
}
- return (
- React.createElement("div", {key: this.state.uri, className: classes.join(' ')},
- React.createElement(ResourceHeader, {className: CLASS_ROOT + "__header",
- resource: this.state.response,
- actions: this.props.actions}),
- React.createElement("div", {className: CLASS_ROOT + "__content"},
- React.createElement(ResourceActivity, {category: this.props.category, uri: this.state.uri}),
- React.createElement("div", {className: CLASS_ROOT + "__attributes"},
- React.createElement(Object, {data: this.state.response})
- ),
- React.createElement("h3", null, "Map"),
- React.createElement(ResourceMap, {uri: this.state.uri})
- )
- )
- );
- }
+ /**
+ * The base implementation of `_.clone` without support for argument juggling
+ * and `this` binding `customizer` functions.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @param {Function} [customizer] The function to customize cloning values.
+ * @param {string} [key] The key of `value`.
+ * @param {Object} [object] The object `value` belongs to.
+ * @param {Array} [stackA=[]] Tracks traversed source objects.
+ * @param {Array} [stackB=[]] Associates clones with source counterparts.
+ * @returns {*} Returns the cloned value.
+ */
+ function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
+ var result;
+ if (customizer) {
+ result = object ? customizer(value, key, object) : customizer(value);
+ }
+ if (result !== undefined) {
+ return result;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result = initCloneArray(value);
+ if (!isDeep) {
+ return arrayCopy(value, result);
+ }
+ } else {
+ var tag = objToString.call(value),
+ isFunc = tag == funcTag;
- });
+ if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
+ result = initCloneObject(isFunc ? {} : value);
+ if (!isDeep) {
+ return baseAssign(result, value);
+ }
+ } else {
+ return cloneableTags[tag]
+ ? initCloneByTag(value, tag, isDeep)
+ : (object ? value : {});
+ }
+ }
+ // Check for circular references and return corresponding clone.
+ stackA || (stackA = []);
+ stackB || (stackB = []);
- module.exports = Resource;
+ var length = stackA.length;
+ while (length--) {
+ if (stackA[length] == value) {
+ return stackB[length];
+ }
+ }
+ // Add the source value to the stack of traversed objects and associate it with its clone.
+ stackA.push(value);
+ stackB.push(result);
+ // Recursively populate clone (susceptible to call stack limits).
+ (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
+ result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
+ });
+ return result;
+ }
-/***/ },
-/* 72 */
-/***/ function(module, exports, __webpack_require__) {
-
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
-
- var mirrorkey = __webpack_require__(83);
-
- module.exports = {
-
- ActionTypes: mirrorkey({
- INDEX_SET_CONTEXT: null,
- INDEX_SET_PARAMS: null,
- INDEX_RESULT: null,
- INDEX_SEARCH_ATTRIBUTE: null,
- INDEX_START_CHANGING: null,
- INDEX_COMMIT_CHANGES: null,
- INDEX_ABANDON_CHANGES: null,
- INDEX_SET_VIEW: null,
- INDEX_SET_SEARCH_MODE: null,
- INDEX_UPDATE_ATTRIBUTE: null,
- INDEX_MOVE_ATTRIBUTE: null,
- INDEX_RESOURCE_ACTIVITY_RESULT: null,
- INDEX_AGGREGATE_RESULT: null,
- INDEX_TREES_AGGREGATED_RESULT: null,
-
- RESOURCE_SETUP: null,
- RESOURCE_RESULT: null,
- RESOURCE_ACTION: null,
-
- DASHBOARD_SETUP: null,
- DASHBOARD_START_CHANGING: null,
- DASHBOARD_COMMIT_CHANGES: null,
- DASHBOARD_ABANDON_CHANGES: null,
- DASHBOARD_ADD_PANEL: null,
- DASHBOARD_REMOVE_PANEL: null,
- DASHBOARD_EDIT_PANEL: null,
- DASHBOARD_UPDATE_PANEL: null,
- DASHBOARD_ORDER_PANELS: null
- })
-
- };
-
-
-/***/ },
-/* 73 */
-/***/ function(module, exports, __webpack_require__) {
-
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
-
- var AppDispatcher = __webpack_require__(44);
- var Constants = __webpack_require__(72);
-
- module.exports = {
-
- setup: function (config) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_SETUP,
- config: config
- });
- },
-
- startChanging: function () {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_START_CHANGING
- });
- },
-
- commitChanges: function () {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_COMMIT_CHANGES
- });
- },
-
- abandonChanges: function () {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_ABANDON_CHANGES
- });
- },
-
- addPanel: function (panel) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_ADD_PANEL,
- panel: panel
- });
- },
-
- removePanel: function (panel) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_REMOVE_PANEL,
- panel: panel
- });
- },
-
- editPanel: function (panel) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_EDIT_PANEL,
- panel: panel
- });
- },
-
- updatePanel: function (index) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_UPDATE_PANEL,
- index: index
- });
- },
-
- orderPanels: function (panels) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.DASHBOARD_ORDER_PANELS,
- panels: panels
- });
- }
-
- };
-
-
-/***/ },
-/* 74 */
-/***/ function(module, exports, __webpack_require__) {
-
- // (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
-
- var _ = __webpack_require__(79);
- var AppDispatcher = __webpack_require__(44);
- var Constants = __webpack_require__(72);
- var Api = __webpack_require__(46);
-
- // translate the params used in the UI to the structure used by the REST API
- function translateToApiParams (params) {
- var apiParams = _.extend({}, params);
- // split search into query and userQuery
- if (apiParams.search) {
-
- // split out query terms for api call, attribute:value terms
- apiParams.query = apiParams.search.tokens.filter(function (token) {
- return token.hasOwnProperty('attribute');
- }).map(function (token) {
- return token.attribute + ":'" + token.value + "'";
- }).join(' ');
- if (apiParams.query.length === 0) {
- delete apiParams.query;
- }
+ /**
+ * The base implementation of `_.create` without support for assigning
+ * properties to the created object.
+ *
+ * @private
+ * @param {Object} prototype The object to inherit from.
+ * @returns {Object} Returns the new object.
+ */
+ var baseCreate = (function() {
+ function Object() {}
+ return function(prototype) {
+ if (isObject(prototype)) {
+ Object.prototype = prototype;
+ var result = new Object;
+ Object.prototype = null;
+ }
+ return result || context.Object();
+ };
+ }());
- apiParams.userQuery = apiParams.search.text;
- if (apiParams.userQuery.length === 0) {
- delete apiParams.userQuery;
+ /**
+ * The base implementation of `_.delay` and `_.defer` which accepts an index
+ * of where to slice the arguments to provide to `func`.
+ *
+ * @private
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {Object} args The arguments provide to `func`.
+ * @returns {number} Returns the timer id.
+ */
+ function baseDelay(func, wait, args) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return setTimeout(function() { func.apply(undefined, args); }, wait);
}
- delete apiParams.search;
- }
-
- return apiParams;
- }
-
- // We throttle loading resource activity to avoid flooding the network and slowing down the UI.
- var pendingTimer = null;
- var pendingGets = [];
- var pendingActivityUris = {};
- var THROTTLE_DELAY = 100; // milliseconds
-
- function getSome () {
- if (pendingGets.length > 0) {
- var getArgs = pendingGets.shift();
- Api.get(getArgs.action, getArgs.restUri, getArgs.apiParams, getArgs.resourceUri);
- clearTimeout(pendingTimer);
- pendingTimer = setTimeout(getSome, THROTTLE_DELAY);
- }
- }
-
- function queueActivity (category, uri) {
- if ('tasks' !== category &&
- 'alerts' !== category &&
- (! Array.isArray(category) || category.indexOf('alerts') === -1) &&
- ! pendingActivityUris[uri]) {
-
- var params = {
- category: ['alerts', 'tasks'],
- query: "associatedResourceUri:'" + uri + "' AND " +
- "(state:'Active' OR state:'Running') AND " +
- "parentTaskUri:'null' AND " +
- "NOT taskType:'Background' AND " +
- //"(NOT state:'New' OR NOT state:'Starting') AND " +
- "NOT stateReason:'ValidationError'",
- sort: 'created:desc',
- start: 0,
- count: 5
- };
- var apiParams = translateToApiParams(params);
- var getArgs = {
- action: Constants.ActionTypes.INDEX_RESOURCE_ACTIVITY_RESULT,
- restUri: '/rest/index/resources',
- apiParams: apiParams,
- resourceUri: uri
- };
-
- pendingGets.push(getArgs);
- pendingActivityUris[uri] = true;
- }
- }
-
- var attributeAggregateTimer = null;
-
- function getAttributeAggregates(getter, index) {
- var attributes;
-
- if (index.params.search.fullText.length > 0) {
- // get aggregated attributes
- attributes = index.attributes.filter(function (attribute) {
- return attribute.aggregate;
- }).map(function (attribute) {
- return attribute.name;
- });
+ /**
+ * The base implementation of `_.difference` which accepts a single array
+ * of values to exclude.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Array} values The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ */
+ function baseDifference(array, values) {
+ var length = array ? array.length : 0,
+ result = [];
- if (attributes.length > 0) {
- getter(index.params, attributes);
- }
+ if (!length) {
+ return result;
+ }
+ var index = -1,
+ indexOf = getIndexOf(),
+ isCommon = indexOf == baseIndexOf,
+ cache = (isCommon && values.length >= 200) ? createCache(values) : null,
+ valuesLength = values.length;
- // if we don't have filter values yet, get them, without any search filter
- attributes = index.attributes.filter(function (attribute) {
- return attribute.filter;
- }).map(function (attribute) {
- return attribute.name;
- });
+ if (cache) {
+ indexOf = cacheIndexOf;
+ isCommon = false;
+ values = cache;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index];
- if (attributes.length > 0) {
- var filterParams = _.extend({}, index.params,
- {search: {fullText: '', tokens: [], text: ''}});
- getter(filterParams, attributes);
- }
- } else {
- attributes = index.attributes.filter(function (attribute) {
- return attribute.aggregate || attribute.filter;
- }).map(function (attribute) {
- return attribute.name;
- });
-
- if (attributes.length > 0) {
- getter(index.params, attributes);
+ if (isCommon && value === value) {
+ var valuesIndex = valuesLength;
+ while (valuesIndex--) {
+ if (values[valuesIndex] === value) {
+ continue outer;
+ }
+ }
+ result.push(value);
+ }
+ else if (indexOf(values, value, 0) < 0) {
+ result.push(value);
+ }
+ }
+ return result;
}
- }
- }
-
- module.exports = {
-
- setContext: function (args) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.INDEX_SET_CONTEXT,
- args: args
- });
- },
- // index is optional, if provided, aggregates will be loaded as well
- getResult: function (params, index) {
- AppDispatcher.handleViewAction({
- type: Constants.ActionTypes.INDEX_SET_PARAMS,
- params: params
- });
+ /**
+ * The base implementation of `_.forEach` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object|string} Returns `collection`.
+ */
+ var baseEach = createBaseEach(baseForOwn);
- var apiParams = translateToApiParams(params);
- pendingActivityUris = {};
- Api.get(Constants.ActionTypes.INDEX_RESULT,
- '/rest/index/resources', apiParams, {params: params});
+ /**
+ * The base implementation of `_.forEachRight` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object|string} Returns `collection`.
+ */
+ var baseEachRight = createBaseEach(baseForOwnRight, true);
- if (index) {
- clearTimeout(attributeAggregateTimer);
- var getter = this.getAggregates;
- attributeAggregateTimer = setTimeout(function () {
- getAttributeAggregates(getter, index);
- }, THROTTLE_DELAY);
+ /**
+ * The base implementation of `_.every` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`
+ */
+ function baseEvery(collection, predicate) {
+ var result = true;
+ baseEach(collection, function(value, index, collection) {
+ result = !!predicate(value, index, collection);
+ return result;
+ });
+ return result;
}
- },
- search: function (search, referenceUri, index) {
- var params = _.extend({}, index.params, {search: search, referenceUri: referenceUri});
- this.getResult(params, index);
- },
+ /**
+ * The base implementation of `_.fill` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ */
+ function baseFill(array, value, start, end) {
+ var length = array.length;
- loadMore: function (index) {
- var params = _.extend({}, index.params);
- params.count += index.pageSize;
- this.getResult(params);
- },
+ start = start == null ? 0 : (+start || 0);
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = (end === undefined || end > length) ? length : (+end || 0);
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : (end >>> 0);
+ start >>>= 0;
- getIndexActivity: function (members) {
- for (var i=0; i {view: , searchMode: , sort: , attributes: }
-
- var _data = {
-
- pageSize: 20, //100,
-
- // defaults will be subsumed by persistent state
- defaults: {
- view: 'table',
- searchMode: 'filters',
- sort: 'name:asc',
- attributes: [{name: 'name', label: 'Name'}] // {name: ,label: }
- },
-
- view: 'table', // which view to show, 'table' or 'tiles'
- searchMode: 'filters', // which style of search to use
- sort: 'name:asc',
- // each array contains attribute objects containing:
- // {name: , label: , visible: , aggregate: , filter: }
- // aggregate have {filteredAggregateResult: [{value: ,count:}]}
- // filter have {unfilteredAggregateResult: [{value: ,count:}]}
- attributes: [],
- includeActivity: false,
-
- params: {
- category: null,
- start: 0,
- count: 0,
- // search: {tokens: [{attribute: , value: , text: } or {text: }], fullText: , text: }
- search: Search.create(''),
- sort: 'name:asc'
- },
-
- // what we receive
- result: {
- members: [],
- start: 0,
- count: 0,
- total: 0,
- unfilteredTotal: 0
- },
-
- uriIndexes: {}, // hash of uri -> index in result.members[]
-
- facetedSearchText: '', // different than params.search.fullText because we strip the trailing ':'
- facetedSearchSuggestions: []
- };
-
- function findAttribute(attributes, attributeName) {
- return attributes.filter(function (attribute) {
- return attribute.name === attributeName;
- })[0];
- }
-
- function clearResults() {
- _data.result = {
- params: {},
- members: [],
- start: 0,
- count: 0,
- total: 0,
- unfilteredTotal: 0
- };
- _data.uriIndexes = {};
- _data.attributes.forEach(function (attribute) {
- delete attribute.filteredAggregateResult;
- });
- }
-
- // construct the key to use for _persistentState
- function categoryKey(category) {
- if (typeof category === 'string') {
- return category;
- } else if (Array.isArray(category)) {
- return category.join(',');
- }
- }
-
- // Provides a default context and initializes the state
- function setContext(args) {
+ /**
+ * The base implementation of `_.isMatch` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Array} props The source property names to match.
+ * @param {Array} values The source values to match.
+ * @param {Array} strictCompareFlags Strict comparison flags for source values.
+ * @param {Function} [customizer] The function to customize comparing objects.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ */
+ function baseIsMatch(object, props, values, strictCompareFlags, customizer) {
+ var index = -1,
+ length = props.length,
+ noCustomizer = !customizer;
- // normalize attributes
- if (args.attributes) {
- // normalize attributes
- args.attributes = args.attributes.map(function (attribute, index) {
- if (typeof attribute === 'string') {
- attribute = {name: attribute};
- }
- if (! attribute.hasOwnProperty('label')) {
- if ('_activity' === attribute.name) {
- attribute.label = 'Activity';
- } else {
- attribute.label = String.toSentenceCase(attribute.name);
+ while (++index < length) {
+ if ((noCustomizer && strictCompareFlags[index])
+ ? values[index] !== object[props[index]]
+ : !(props[index] in object)
+ ) {
+ return false;
}
}
- if (! attribute.hasOwnProperty('visible')) {
- attribute.visible = true;
- }
- attribute.index = index;
- return attribute;
- });
- }
-
- // set defaults
- _data.defaults.view = args.view || 'table';
- _data.defaults.searchMode = args.searchMode || 'filters';
- _data.defaults.sort = args.sort || 'name:asc';
- _data.defaults.attributes = args.attributes || [];
-
- _persistentState = JSON.parse(localStorage.getItem('IndexStore__state') || '{}');
- var key = categoryKey(args.category);
- // initialize persistent state if we haven't yet
- if (! _persistentState.hasOwnProperty(key)) {
- _persistentState[key] = {
- view: _data.defaults.view,
- searchMode: _data.defaults.searchMode,
- sort: _data.defaults.sort,
- attributes: _data.defaults.attributes
- };
- }
-
- // set current state
- var persistent = _persistentState[key];
- _data.view = persistent.view;
- _data.searchMode = persistent.searchMode;
- _data.sort = persistent.sort;
- _data.attributes = persistent.attributes;
-
- // add any default attributes that weren't persisted
- _data.defaults.attributes.forEach(function (attribute) {
- if (! findAttribute(_data.attributes, attribute.name)) {
- attribute.visible = false;
- _data.attributes.push(attribute);
- }
- });
+ index = -1;
+ while (++index < length) {
+ var key = props[index],
+ objValue = object[key],
+ srcValue = values[index];
- _data.includeActivity = false;
- _data.attributes.forEach(function (attribute) {
- // preserve render() function
- _data.defaults.attributes.some(function (defaultAttribute) {
- if (defaultAttribute.name === attribute.name) {
- if (defaultAttribute.hasOwnProperty('render')) {
- attribute.render = defaultAttribute.render;
+ if (noCustomizer && strictCompareFlags[index]) {
+ var result = objValue !== undefined || (key in object);
+ } else {
+ result = customizer ? customizer(objValue, srcValue, key) : undefined;
+ if (result === undefined) {
+ result = baseIsEqual(srcValue, objValue, customizer, true);
+ }
}
- if (defaultAttribute.hasLink) {
- attribute.hasLink = defaultAttribute.hasLink;
+ if (!result) {
+ return false;
}
- return true;
- }
- });
- if (attribute.visible && attribute.name === '_activity') {
- _data.includeActivity = true;
- }
- delete attribute.unfilteredAggregateResult;
- });
-
- _data.params = {
- category: args.category,
- start: 0,
- count: _data.pageSize,
- search: Search.create(''),
- sort: _data.sort
- };
-
- clearResults();
- }
-
- // attributes we don't allow the user to see when searching
- var BLACKLIST = {'category': true, 'type': true, 'uri': true, 'eTag': true};
-
- // add additional attributes found in an index result to the list of available attributes
- function addAttributesFromResult(obj) {
- _.forOwn(obj, function (value, name) {
- var attribute = findAttribute(_data.attributes, name);
- if (! attribute && ! BLACKLIST[name]) {
-
- if (typeof obj[name] !== 'object') {
- attribute = {
- name: name,
- label: String.toSentenceCase(name),
- visible: false
- };
- _data.attributes.push(attribute);
- } else if ('attributes' === name) {
- addAttributesFromResult(value);
}
+ return true;
}
- });
- }
-
- // context is _data for basic usage and _data.pendingChanges while editing
- function sortAttributes(context) {
- // sort, first by show order, then by name
- context.attributes.sort(function (a1, a2) {
- if (a1.visible && a2.visible) {
- return (a1.index < a2.index ? -1 : +1);
- } else if (! a1.visible && ! a2.visible) {
- return AlphaNum.compare(a1.name, a2.name);
- } else {
- return a1.visible ? -1 : +1;
- }
- });
- }
- // indicate which attribute values are currently being filtered for
- function markActiveFilters() {
- _data.attributes.forEach(function (attribute) {
- if (attribute.unfilteredAggregateResult) {
- attribute.unfilteredAggregateResult.counts.forEach(function (value) {
- value.filterActive = _data.params.search.tokens.some(function (token) {
- return token.attribute === attribute.name && token.value === value.value;
- });
- });
- }
- });
- }
+ /**
+ * The base implementation of `_.map` without support for callback shorthands
+ * and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function baseMap(collection, iteratee) {
+ var index = -1,
+ result = isArrayLike(collection) ? Array(collection.length) : [];
- // construct the appropriate faceted search suggestions based on the last search text term
- function buildFacetedSearchSuggestions() {
- _data.facetedSearchSuggestions = [];
- var text = _data.facetedSearchText;
-
- // match only last term and only if there isn't a trailing space
- var lastChar = text[text.length - 1];
- var matches = text.match(/\S+/g);
- var term = '';
- if (' ' !== lastChar && matches && matches.length > 0) {
- term = matches[matches.length-1].toLowerCase();
- }
- var parts = term.split(':');
- var exp;
- if (parts.length > 1) {
-
- // attribute:value
- exp = new RegExp(parts[1] + '[^$]', 'i');
- var attribute = findAttribute(_data.attributes, parts[0]);
- if (attribute.unfilteredAggregateResult) {
- attribute.unfilteredAggregateResult.counts.forEach(function (count) {
- if (exp.test(count.value)) {
- _data.facetedSearchSuggestions.push({term: count.value, count: count.count});
- }
+ baseEach(collection, function(value, key, collection) {
+ result[++index] = iteratee(value, key, collection);
});
+ return result;
}
- } else {
+ /**
+ * The base implementation of `_.matches` which does not clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new function.
+ */
+ function baseMatches(source) {
+ var props = keys(source),
+ length = props.length;
- // attribute
- exp = new RegExp(parts[0] + '[^$]', 'i');
- _data.attributes.forEach(function (attribute) {
- if (exp.test(attribute.name) && '_activity' !== attribute.name) {
- _data.facetedSearchSuggestions.push({term: attribute.name + ':'});
+ if (!length) {
+ return constant(true);
}
- });
- }
-
- // sort
- _data.facetedSearchSuggestions.sort(function (s1, s2) {
- return AlphaNum.compare(s1.term, s2.term);
- });
- }
-
- // set the parameters that will be used for subsequent results
- function setParams(params) {
- _data.params = params;
- _data.facetedSearchText = params.search.fullText;
- markActiveFilters();
-
- // clear out result so we don't use old results after we've asked for new ones
- clearResults();
- }
-
- // record a result from the index service
- function setResult(result) {
- _data.result = result;
-
- // save uri -> index to speed up lookups by uri
- _data.uriIndexes = {};
- _data.result.members.forEach(function (member, index) {
- _data.uriIndexes[member.uri] = index;
- });
-
- // save attributes so we can use them as faceted search suggestions
- if (_data.result.members.length > 1) {
- addAttributesFromResult(_data.result.members[0]);
- sortAttributes(_data);
- }
-
- buildFacetedSearchSuggestions();
- }
-
- // save the activity result for the indicated resource
- function setResourceActivityResult(result, uri) {
- if (_data.uriIndexes.hasOwnProperty(uri)) {
- var member = _data.result.members[_data.uriIndexes[uri]];
- member._activity = result;
- }
- }
+ if (length == 1) {
+ var key = props[0],
+ value = source[key];
- // save the aggregate results
- function setAggregateResult(result, context) {
- // ignote results initiated from the Dashboard
- if (context.params.search && context.params.search.tokens &&
- context.params.category === _data.params.category) {
- result.forEach(function (attributeResult) {
- var attribute = findAttribute(_data.attributes, attributeResult.attribute);
- if (attribute) {
- if (context.params.search.fullText.length > 0) {
- attribute.filteredAggregateResult = attributeResult;
- } else {
- attribute.unfilteredAggregateResult = attributeResult;
+ if (isStrictComparable(value)) {
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ return object[key] === value && (value !== undefined || (key in toObject(object)));
+ };
}
}
- });
- markActiveFilters();
- buildFacetedSearchSuggestions();
- }
- }
+ var values = Array(length),
+ strictCompareFlags = Array(length);
- function startChanging() {
- _data.pendingChanges = {
- view: _data.view,
- searchMode: _data.searchMode,
- attributes: _data.attributes.slice(0)
- };
- }
-
- function pruneAttributesForPersistence(attributes) {
- return attributes.filter(function (attribute) {
- return attribute.visible || attribute.aggregate || attribute.filter;
- }).map(function (attribute) {
- return {
- name: attribute.name,
- label: attribute.label,
- visible: attribute.visible || false,
- aggregate: attribute.aggregate || false,
- filter: attribute.filter || false
- };
- });
- }
-
- function commitChanges() {
- _data.view = _data.pendingChanges.view;
- _data.searchMode = _data.pendingChanges.searchMode;
- _data.attributes = _data.pendingChanges.attributes;
-
- var key = categoryKey(_data.params.category);
- _persistentState[key].view = _data.view;
- _persistentState[key].searchMode = _data.searchMode;
- _persistentState[key].attributes = pruneAttributesForPersistence(_data.attributes);
- localStorage.setItem('IndexStore__state', JSON.stringify(_persistentState));
- }
-
- function abandonChanges() {
- _data.pendingChanges = null;
- }
-
- function setView(view) {
- _data.pendingChanges.view = view;
- }
-
- function setSearchMode(searchMode) {
- _data.pendingChanges.searchMode = searchMode;
- }
-
- function updateAttribute(attributeArg) {
- var attribute = findAttribute(_data.pendingChanges.attributes, attributeArg.name);
- attribute.visible = attributeArg.visible;
- attribute.aggregate = attributeArg.aggregate;
- attribute.filter = attributeArg.filter;
- sortAttributes(_data.pendingChanges);
- }
-
- function moveAttribute(fromIndex, toIndex) {
- var attributes = _data.pendingChanges.attributes;
- attributes.splice(toIndex, 0, attributes.splice(fromIndex, 1)[0]);
- _data.pendingChanges.attributes.forEach(function (attribute, index) {
- attribute.index = index;
- });
- sortAttributes(_data.pendingChanges);
- }
-
- var IndexStore = _.extend({}, EventEmitter.prototype, {
-
- // public methods used by Controller-View to operate on data
- getAll: function() {
- return _data;
- },
-
- nextUri: function (resourceUri) {
- var resultUri = null;
- if (_data.uriIndexes.hasOwnProperty(resourceUri)) {
- var index = _data.uriIndexes[resourceUri] + 1;
- if (index < _data.result.members.length) {
- resultUri = _data.result.members[index].uri;
+ while (length--) {
+ value = source[props[length]];
+ values[length] = value;
+ strictCompareFlags[length] = isStrictComparable(value);
}
+ return function(object) {
+ return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags);
+ };
}
- return resultUri;
- },
- previousUri: function (resourceUri) {
- var resultUri = null;
- if (_data.uriIndexes.hasOwnProperty(resourceUri)) {
- var index = _data.uriIndexes[resourceUri] - 1;
- if (index >= 0) {
- resultUri = _data.result.members[index].uri;
- }
- }
- return resultUri;
- },
+ /**
+ * The base implementation of `_.matchesProperty` which does not which does
+ * not clone `value`.
+ *
+ * @private
+ * @param {string} path The path of the property to get.
+ * @param {*} value The value to compare.
+ * @returns {Function} Returns the new function.
+ */
+ function baseMatchesProperty(path, value) {
+ var isArr = isArray(path),
+ isCommon = isKey(path) && isStrictComparable(value),
+ pathKey = (path + '');
- areSameCategories: function (c1, c2) {
- if (typeof c1 === 'string' && c1 === c2) {
- return true;
- } else if (Array.isArray(c1) && Array.isArray(c2)) {
- if (c1.length !== c2.length) {
- return false;
- }
- for (var i=0; i length ? 0 : (length + start);
+ }
+ end = (end === undefined || end > length) ? length : (+end || 0);
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : ((end - start) >>> 0);
+ start >>>= 0;
- var _ = __webpack_require__(79);
- var AppDispatcher = __webpack_require__(44);
- var EventEmitter = __webpack_require__(81).EventEmitter;
- var Constants = __webpack_require__(72);
-
- var _data = {
- category: null,
- uri: null,
- response: null,
- activity: {},
- treesAggregated: {}
- };
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = array[index + start];
+ }
+ return result;
+ }
- // add private functions to modify data
- function setup(uri, category) {
- _data.category = category;
- _data.uri = uri;
- _data.response = null;
- }
+ /**
+ * The base implementation of `_.some` without support for callback shorthands
+ * and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function baseSome(collection, predicate) {
+ var result;
- function setResult(result) {
- _data.response = result;
- }
+ baseEach(collection, function(value, index, collection) {
+ result = predicate(value, index, collection);
+ return !result;
+ });
+ return !!result;
+ }
- function setActivityResult(uri, result) {
- if (uri === _data.uri) {
- _data.activity = result;
- }
- }
+ /**
+ * The base implementation of `_.sortBy` which uses `comparer` to define
+ * the sort order of `array` and replaces criteria objects with their
+ * corresponding values.
+ *
+ * @private
+ * @param {Array} array The array to sort.
+ * @param {Function} comparer The function to define sort order.
+ * @returns {Array} Returns `array`.
+ */
+ function baseSortBy(array, comparer) {
+ var length = array.length;
- function setTreesAggregatedResult(uri, result) {
- if (uri === _data.uri) {
- _data.treesAggregated = result;
- }
- }
+ array.sort(comparer);
+ while (length--) {
+ array[length] = array[length].value;
+ }
+ return array;
+ }
- function setActionResult(result) {
- _data.task.uri = result.taskUri;
- }
+ /**
+ * The base implementation of `_.sortByOrder` without param guards.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+ * @param {boolean[]} orders The sort orders of `iteratees`.
+ * @returns {Array} Returns the new sorted array.
+ */
+ function baseSortByOrder(collection, iteratees, orders) {
+ var callback = getCallback(),
+ index = -1;
- var ResourceStore = _.extend({}, EventEmitter.prototype, {
+ iteratees = arrayMap(iteratees, function(iteratee) { return callback(iteratee); });
- // public methods used by Controller-View to operate on data
- getAll: function() {
- return _data;
- },
+ var result = baseMap(collection, function(value) {
+ var criteria = arrayMap(iteratees, function(iteratee) { return iteratee(value); });
+ return { 'criteria': criteria, 'index': ++index, 'value': value };
+ });
- // Allow Controller-View to register itself with store
- addChangeListener: function(callback) {
- this.on(Constants.CHANGE_EVENT, callback);
- },
- removeChangeListener: function(callback) {
- this.removeListener(Constants.CHANGE_EVENT, callback);
- },
- // triggers change listener above, firing controller-view callback
- emitChange: function() {
- this.emit(Constants.CHANGE_EVENT);
- },
+ return baseSortBy(result, function(object, other) {
+ return compareMultiple(object, other, orders);
+ });
+ }
- // register store with dispatcher, allowing actions to flow through
- dispatcherIndex: AppDispatcher.register(function(payload) {
- var action = payload.action;
+ /**
+ * The base implementation of `_.sum` without support for callback shorthands
+ * and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {number} Returns the sum.
+ */
+ function baseSum(collection, iteratee) {
+ var result = 0;
+ baseEach(collection, function(value, index, collection) {
+ result += +iteratee(value, index, collection) || 0;
+ });
+ return result;
+ }
- switch(action.type) {
+ /**
+ * The base implementation of `_.uniq` without support for callback shorthands
+ * and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The function invoked per iteration.
+ * @returns {Array} Returns the new duplicate-value-free array.
+ */
+ function baseUniq(array, iteratee) {
+ var index = -1,
+ indexOf = getIndexOf(),
+ length = array.length,
+ isCommon = indexOf == baseIndexOf,
+ isLarge = isCommon && length >= 200,
+ seen = isLarge ? createCache() : null,
+ result = [];
- case Constants.ActionTypes.RESOURCE_SETUP:
- setup(action.uri, action.category);
- ResourceStore.emitChange();
- break;
+ if (seen) {
+ indexOf = cacheIndexOf;
+ isCommon = false;
+ } else {
+ isLarge = false;
+ seen = iteratee ? [] : result;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value, index, array) : value;
- case Constants.ActionTypes.RESOURCE_RESULT:
- setResult(action.response);
- ResourceStore.emitChange();
- break;
+ if (isCommon && value === value) {
+ var seenIndex = seen.length;
+ while (seenIndex--) {
+ if (seen[seenIndex] === computed) {
+ continue outer;
+ }
+ }
+ if (iteratee) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ else if (indexOf(seen, computed, 0) < 0) {
+ if (iteratee || isLarge) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
- case Constants.ActionTypes.INDEX_RESOURCE_ACTIVITY_RESULT:
- setActivityResult(action.context, action.response);
- ResourceStore.emitChange();
- break;
+ /**
+ * The base implementation of `_.values` and `_.valuesIn` which creates an
+ * array of `object` property values corresponding to the property names
+ * of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the array of property values.
+ */
+ function baseValues(object, props) {
+ var index = -1,
+ length = props.length,
+ result = Array(length);
- case Constants.ActionTypes.INDEX_TREES_AGGREGATED_RESULT:
- setTreesAggregatedResult(action.context, action.response);
- ResourceStore.emitChange();
- break;
+ while (++index < length) {
+ result[index] = object[props[index]];
+ }
+ return result;
+ }
- case Constants.ActionTypes.RESOURCE_ACTION:
- setActionResult(action.response);
- ResourceStore.emitChange();
- break;
+ /**
+ * The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`,
+ * and `_.takeWhile` without support for callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseWhile(array, predicate, isDrop, fromRight) {
+ var length = array.length,
+ index = fromRight ? length : -1;
+ while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
+ return isDrop
+ ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
+ : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
}
- })
-
- });
- module.exports = ResourceStore;
+ /**
+ * The base implementation of `wrapperValue` which returns the result of
+ * performing a sequence of actions on the unwrapped `value`, where each
+ * successive action is supplied the return value of the previous.
+ *
+ * @private
+ * @param {*} value The unwrapped value.
+ * @param {Array} actions Actions to peform to resolve the unwrapped value.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseWrapperValue(value, actions) {
+ var result = value;
+ if (result instanceof LazyWrapper) {
+ result = result.value();
+ }
+ var index = -1,
+ length = actions.length;
+ while (++index < length) {
+ var args = [result],
+ action = actions[index];
-/***/ },
-/* 79 */
-/***/ function(module, exports, __webpack_require__) {
+ push.apply(args, action.args);
+ result = action.func.apply(action.thisArg, args);
+ }
+ return result;
+ }
- var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/**
- * @license
- * lodash 3.7.0 (Custom Build)
- * Build: `lodash modern -d -o ./index.js`
- * Copyright 2012-2015 The Dojo Foundation
- * Based on Underscore.js 1.8.3
- * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license
- */
- ;(function() {
-
- /** Used as a safe reference for `undefined` in pre-ES5 environments. */
- var undefined;
+ /**
+ * Performs a binary search of `array` to determine the index at which `value`
+ * should be inserted into `array` in order to maintain its sort order.
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function binaryIndex(array, value, retHighest) {
+ var low = 0,
+ high = array ? array.length : low;
- /** Used as the semantic version number. */
- var VERSION = '3.7.0';
+ if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
+ while (low < high) {
+ var mid = (low + high) >>> 1,
+ computed = array[mid];
- /** Used to compose bitmasks for wrapper metadata. */
- var BIND_FLAG = 1,
- BIND_KEY_FLAG = 2,
- CURRY_BOUND_FLAG = 4,
- CURRY_FLAG = 8,
- CURRY_RIGHT_FLAG = 16,
- PARTIAL_FLAG = 32,
- PARTIAL_RIGHT_FLAG = 64,
- ARY_FLAG = 128,
- REARG_FLAG = 256;
+ if (retHighest ? (computed <= value) : (computed < value)) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return high;
+ }
+ return binaryIndexBy(array, value, identity, retHighest);
+ }
- /** Used as default options for `_.trunc`. */
- var DEFAULT_TRUNC_LENGTH = 30,
- DEFAULT_TRUNC_OMISSION = '...';
+ /**
+ * This function is like `binaryIndex` except that it invokes `iteratee` for
+ * `value` and each element of `array` to compute their sort ranking. The
+ * iteratee is invoked with one argument; (value).
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function binaryIndexBy(array, value, iteratee, retHighest) {
+ value = iteratee(value);
- /** Used to detect when a function becomes hot. */
- var HOT_COUNT = 150,
- HOT_SPAN = 16;
+ var low = 0,
+ high = array ? array.length : 0,
+ valIsNaN = value !== value,
+ valIsUndef = value === undefined;
- /** Used to indicate the type of lazy iteratees. */
- var LAZY_DROP_WHILE_FLAG = 0,
- LAZY_FILTER_FLAG = 1,
- LAZY_MAP_FLAG = 2;
+ while (low < high) {
+ var mid = floor((low + high) / 2),
+ computed = iteratee(array[mid]),
+ isReflexive = computed === computed;
- /** Used as the `TypeError` message for "Functions" methods. */
- var FUNC_ERROR_TEXT = 'Expected a function';
+ if (valIsNaN) {
+ var setLow = isReflexive || retHighest;
+ } else if (valIsUndef) {
+ setLow = isReflexive && (retHighest || computed !== undefined);
+ } else {
+ setLow = retHighest ? (computed <= value) : (computed < value);
+ }
+ if (setLow) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return nativeMin(high, MAX_ARRAY_INDEX);
+ }
- /** Used as the internal argument placeholder. */
- var PLACEHOLDER = '__lodash_placeholder__';
+ /**
+ * A specialized version of `baseCallback` which only supports `this` binding
+ * and specifying the number of arguments to provide to `func`.
+ *
+ * @private
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {number} [argCount] The number of arguments to provide to `func`.
+ * @returns {Function} Returns the callback.
+ */
+ function bindCallback(func, thisArg, argCount) {
+ if (typeof func != 'function') {
+ return identity;
+ }
+ if (thisArg === undefined) {
+ return func;
+ }
+ switch (argCount) {
+ case 1: return function(value) {
+ return func.call(thisArg, value);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(thisArg, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(thisArg, accumulator, value, index, collection);
+ };
+ case 5: return function(value, other, key, object, source) {
+ return func.call(thisArg, value, other, key, object, source);
+ };
+ }
+ return function() {
+ return func.apply(thisArg, arguments);
+ };
+ }
- /** `Object#toString` result references. */
- var argsTag = '[object Arguments]',
- arrayTag = '[object Array]',
- boolTag = '[object Boolean]',
- dateTag = '[object Date]',
- errorTag = '[object Error]',
- funcTag = '[object Function]',
- mapTag = '[object Map]',
- numberTag = '[object Number]',
- objectTag = '[object Object]',
- regexpTag = '[object RegExp]',
- setTag = '[object Set]',
- stringTag = '[object String]',
- weakMapTag = '[object WeakMap]';
+ /**
+ * Creates a clone of the given array buffer.
+ *
+ * @private
+ * @param {ArrayBuffer} buffer The array buffer to clone.
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
+ */
+ function bufferClone(buffer) {
+ return bufferSlice.call(buffer, 0);
+ }
+ if (!bufferSlice) {
+ // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`.
+ bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) {
+ var byteLength = buffer.byteLength,
+ floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0,
+ offset = floatLength * FLOAT64_BYTES_PER_ELEMENT,
+ result = new ArrayBuffer(byteLength);
- var arrayBufferTag = '[object ArrayBuffer]',
- float32Tag = '[object Float32Array]',
- float64Tag = '[object Float64Array]',
- int8Tag = '[object Int8Array]',
- int16Tag = '[object Int16Array]',
- int32Tag = '[object Int32Array]',
- uint8Tag = '[object Uint8Array]',
- uint8ClampedTag = '[object Uint8ClampedArray]',
- uint16Tag = '[object Uint16Array]',
- uint32Tag = '[object Uint32Array]';
+ if (floatLength) {
+ var view = new Float64Array(result, 0, floatLength);
+ view.set(new Float64Array(buffer, 0, floatLength));
+ }
+ if (byteLength != offset) {
+ view = new Uint8Array(result, offset);
+ view.set(new Uint8Array(buffer, offset));
+ }
+ return result;
+ };
+ }
- /** Used to match empty string literals in compiled template source. */
- var reEmptyStringLeading = /\b__p \+= '';/g,
- reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
- reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+ /**
+ * Creates an array that is the composition of partially applied arguments,
+ * placeholders, and provided arguments into a single array of arguments.
+ *
+ * @private
+ * @param {Array|Object} args The provided arguments.
+ * @param {Array} partials The arguments to prepend to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgs(args, partials, holders) {
+ var holdersLength = holders.length,
+ argsIndex = -1,
+ argsLength = nativeMax(args.length - holdersLength, 0),
+ leftIndex = -1,
+ leftLength = partials.length,
+ result = Array(argsLength + leftLength);
- /** Used to match HTML entities and HTML characters. */
- var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
- reUnescapedHtml = /[&<>"'`]/g,
- reHasEscapedHtml = RegExp(reEscapedHtml.source),
- reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+ while (++leftIndex < leftLength) {
+ result[leftIndex] = partials[leftIndex];
+ }
+ while (++argsIndex < holdersLength) {
+ result[holders[argsIndex]] = args[argsIndex];
+ }
+ while (argsLength--) {
+ result[leftIndex++] = args[argsIndex++];
+ }
+ return result;
+ }
- /** Used to match template delimiters. */
- var reEscape = /<%-([\s\S]+?)%>/g,
- reEvaluate = /<%([\s\S]+?)%>/g,
- reInterpolate = /<%=([\s\S]+?)%>/g;
+ /**
+ * This function is like `composeArgs` except that the arguments composition
+ * is tailored for `_.partialRight`.
+ *
+ * @private
+ * @param {Array|Object} args The provided arguments.
+ * @param {Array} partials The arguments to append to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgsRight(args, partials, holders) {
+ var holdersIndex = -1,
+ holdersLength = holders.length,
+ argsIndex = -1,
+ argsLength = nativeMax(args.length - holdersLength, 0),
+ rightIndex = -1,
+ rightLength = partials.length,
+ result = Array(argsLength + rightLength);
- /** Used to match property names within property paths. */
- var reIsDeepProp = /\.|\[(?:[^[\]]+|(["'])(?:(?!\1)[^\n\\]|\\.)*?)\1\]/,
- reIsPlainProp = /^\w*$/,
- rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
+ while (++argsIndex < argsLength) {
+ result[argsIndex] = args[argsIndex];
+ }
+ var offset = argsIndex;
+ while (++rightIndex < rightLength) {
+ result[offset + rightIndex] = partials[rightIndex];
+ }
+ while (++holdersIndex < holdersLength) {
+ result[offset + holders[holdersIndex]] = args[argsIndex++];
+ }
+ return result;
+ }
- /**
- * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special).
- * In addition to special characters the forward slash is escaped to allow for
- * easier `eval` use and `Function` compilation.
- */
- var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
- reHasRegExpChars = RegExp(reRegExpChars.source);
+ /**
+ * Creates a function that aggregates a collection, creating an accumulator
+ * object composed from the results of running each element in the collection
+ * through an iteratee.
+ *
+ * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`,
+ * and `_.partition`.
+ *
+ * @private
+ * @param {Function} setter The function to set keys and values of the accumulator object.
+ * @param {Function} [initializer] The function to initialize the accumulator object.
+ * @returns {Function} Returns the new aggregator function.
+ */
+ function createAggregator(setter, initializer) {
+ return function(collection, iteratee, thisArg) {
+ var result = initializer ? initializer() : {};
+ iteratee = getCallback(iteratee, thisArg, 3);
- /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */
- var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
+ if (isArray(collection)) {
+ var index = -1,
+ length = collection.length;
- /** Used to match backslashes in property paths. */
- var reEscapeChar = /\\(\\)?/g;
+ while (++index < length) {
+ var value = collection[index];
+ setter(result, value, iteratee(value, index, collection), collection);
+ }
+ } else {
+ baseEach(collection, function(value, key, collection) {
+ setter(result, value, iteratee(value, key, collection), collection);
+ });
+ }
+ return result;
+ };
+ }
- /** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */
- var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+ /**
+ * Creates a function that assigns properties of source object(s) to a given
+ * destination object.
+ *
+ * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`.
+ *
+ * @private
+ * @param {Function} assigner The function to assign values.
+ * @returns {Function} Returns the new assigner function.
+ */
+ function createAssigner(assigner) {
+ return restParam(function(object, sources) {
+ var index = -1,
+ length = object == null ? 0 : sources.length,
+ customizer = length > 2 && sources[length - 2],
+ guard = length > 2 && sources[2],
+ thisArg = length > 1 && sources[length - 1];
- /** Used to match `RegExp` flags from their coerced string values. */
- var reFlags = /\w*$/;
+ if (typeof customizer == 'function') {
+ customizer = bindCallback(customizer, thisArg, 5);
+ length -= 2;
+ } else {
+ customizer = typeof thisArg == 'function' ? thisArg : null;
+ length -= (customizer ? 1 : 0);
+ }
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? null : customizer;
+ length = 1;
+ }
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, customizer);
+ }
+ }
+ return object;
+ });
+ }
- /** Used to detect hexadecimal string values. */
- var reHasHexPrefix = /^0[xX]/;
+ /**
+ * Creates a `baseEach` or `baseEachRight` function.
+ *
+ * @private
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseEach(eachFunc, fromRight) {
+ return function(collection, iteratee) {
+ var length = collection ? getLength(collection) : 0;
+ if (!isLength(length)) {
+ return eachFunc(collection, iteratee);
+ }
+ var index = fromRight ? length : -1,
+ iterable = toObject(collection);
- /** Used to detect host constructors (Safari > 5). */
- var reIsHostCtor = /^\[object .+?Constructor\]$/;
+ while ((fromRight ? index-- : ++index < length)) {
+ if (iteratee(iterable[index], index, iterable) === false) {
+ break;
+ }
+ }
+ return collection;
+ };
+ }
- /** Used to match latin-1 supplementary letters (excluding mathematical operators). */
- var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
+ /**
+ * Creates a base function for `_.forIn` or `_.forInRight`.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseFor(fromRight) {
+ return function(object, iteratee, keysFunc) {
+ var iterable = toObject(object),
+ props = keysFunc(object),
+ length = props.length,
+ index = fromRight ? length : -1;
- /** Used to ensure capturing order of template delimiters. */
- var reNoMatch = /($^)/;
+ while ((fromRight ? index-- : ++index < length)) {
+ var key = props[index];
+ if (iteratee(iterable[key], key, iterable) === false) {
+ break;
+ }
+ }
+ return object;
+ };
+ }
- /** Used to match unescaped characters in compiled string literals. */
- var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+ /**
+ * Creates a function that wraps `func` and invokes it with the `this`
+ * binding of `thisArg`.
+ *
+ * @private
+ * @param {Function} func The function to bind.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @returns {Function} Returns the new bound function.
+ */
+ function createBindWrapper(func, thisArg) {
+ var Ctor = createCtorWrapper(func);
- /** Used to match words to create compound words. */
- var reWords = (function() {
- var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]',
- lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+';
+ function wrapper() {
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return fn.apply(thisArg, arguments);
+ }
+ return wrapper;
+ }
- return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g');
- }());
+ /**
+ * Creates a `Set` cache object to optimize linear searches of large arrays.
+ *
+ * @private
+ * @param {Array} [values] The values to cache.
+ * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`.
+ */
+ var createCache = !(nativeCreate && Set) ? constant(null) : function(values) {
+ return new SetCache(values);
+ };
- /** Used to detect and test for whitespace. */
- var whitespace = (
- // Basic whitespace characters.
- ' \t\x0b\f\xa0\ufeff' +
+ /**
+ * Creates a function that produces compound words out of the words in a
+ * given string.
+ *
+ * @private
+ * @param {Function} callback The function to combine each word.
+ * @returns {Function} Returns the new compounder function.
+ */
+ function createCompounder(callback) {
+ return function(string) {
+ var index = -1,
+ array = words(deburr(string)),
+ length = array.length,
+ result = '';
- // Line terminators.
- '\n\r\u2028\u2029' +
+ while (++index < length) {
+ result = callback(result, array[index], index);
+ }
+ return result;
+ };
+ }
- // Unicode category "Zs" space separators.
- '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
- );
+ /**
+ * Creates a function that produces an instance of `Ctor` regardless of
+ * whether it was invoked as part of a `new` expression or by `call` or `apply`.
+ *
+ * @private
+ * @param {Function} Ctor The constructor to wrap.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createCtorWrapper(Ctor) {
+ return function() {
+ var thisBinding = baseCreate(Ctor.prototype),
+ result = Ctor.apply(thisBinding, arguments);
- /** Used to assign default `context` object properties. */
- var contextProps = [
- 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
- 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number',
- 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document',
- 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',
- 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
- 'window'
- ];
+ // Mimic the constructor's `return` behavior.
+ // See https://es5.github.io/#x13.2.2 for more details.
+ return isObject(result) ? result : thisBinding;
+ };
+ }
- /** Used to make template sourceURLs easier to identify. */
- var templateCounter = -1;
+ /**
+ * Creates a `_.curry` or `_.curryRight` function.
+ *
+ * @private
+ * @param {boolean} flag The curry bit flag.
+ * @returns {Function} Returns the new curry function.
+ */
+ function createCurry(flag) {
+ function curryFunc(func, arity, guard) {
+ if (guard && isIterateeCall(func, arity, guard)) {
+ arity = null;
+ }
+ var result = createWrapper(func, flag, null, null, null, null, null, arity);
+ result.placeholder = curryFunc.placeholder;
+ return result;
+ }
+ return curryFunc;
+ }
- /** Used to identify `toStringTag` values of typed arrays. */
- var typedArrayTags = {};
- typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
- typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
- typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
- typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
- typedArrayTags[uint32Tag] = true;
- typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
- typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
- typedArrayTags[dateTag] = typedArrayTags[errorTag] =
- typedArrayTags[funcTag] = typedArrayTags[mapTag] =
- typedArrayTags[numberTag] = typedArrayTags[objectTag] =
- typedArrayTags[regexpTag] = typedArrayTags[setTag] =
- typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
+ /**
+ * Creates a `_.max` or `_.min` function.
+ *
+ * @private
+ * @param {Function} arrayFunc The function to get the extremum value from an array.
+ * @param {boolean} [isMin] Specify returning the minimum, instead of the maximum,
+ * extremum value.
+ * @returns {Function} Returns the new extremum function.
+ */
+ function createExtremum(arrayFunc, isMin) {
+ return function(collection, iteratee, thisArg) {
+ if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
+ iteratee = null;
+ }
+ var func = getCallback(),
+ noIteratee = iteratee == null;
- /** Used to identify `toStringTag` values supported by `_.clone`. */
- var cloneableTags = {};
- cloneableTags[argsTag] = cloneableTags[arrayTag] =
- cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
- cloneableTags[dateTag] = cloneableTags[float32Tag] =
- cloneableTags[float64Tag] = cloneableTags[int8Tag] =
- cloneableTags[int16Tag] = cloneableTags[int32Tag] =
- cloneableTags[numberTag] = cloneableTags[objectTag] =
- cloneableTags[regexpTag] = cloneableTags[stringTag] =
- cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
- cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
- cloneableTags[errorTag] = cloneableTags[funcTag] =
- cloneableTags[mapTag] = cloneableTags[setTag] =
- cloneableTags[weakMapTag] = false;
+ if (!(func === baseCallback && noIteratee)) {
+ noIteratee = false;
+ iteratee = func(iteratee, thisArg, 3);
+ }
+ if (noIteratee) {
+ var isArr = isArray(collection);
+ if (!isArr && isString(collection)) {
+ iteratee = charAtCallback;
+ } else {
+ return arrayFunc(isArr ? collection : toIterable(collection));
+ }
+ }
+ return extremumBy(collection, iteratee, isMin);
+ };
+ }
- /** Used as an internal `_.debounce` options object by `_.throttle`. */
- var debounceOptions = {
- 'leading': false,
- 'maxWait': 0,
- 'trailing': false
- };
+ /**
+ * Creates a `_.find` or `_.findLast` function.
+ *
+ * @private
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new find function.
+ */
+ function createFind(eachFunc, fromRight) {
+ return function(collection, predicate, thisArg) {
+ predicate = getCallback(predicate, thisArg, 3);
+ if (isArray(collection)) {
+ var index = baseFindIndex(collection, predicate, fromRight);
+ return index > -1 ? collection[index] : undefined;
+ }
+ return baseFind(collection, predicate, eachFunc);
+ };
+ }
- /** Used to map latin-1 supplementary letters to basic latin letters. */
- var deburredLetters = {
- '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
- '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
- '\xc7': 'C', '\xe7': 'c',
- '\xd0': 'D', '\xf0': 'd',
- '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
- '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
- '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
- '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
- '\xd1': 'N', '\xf1': 'n',
- '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
- '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
- '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
- '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
- '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
- '\xc6': 'Ae', '\xe6': 'ae',
- '\xde': 'Th', '\xfe': 'th',
- '\xdf': 'ss'
- };
+ /**
+ * Creates a `_.findIndex` or `_.findLastIndex` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new find function.
+ */
+ function createFindIndex(fromRight) {
+ return function(array, predicate, thisArg) {
+ if (!(array && array.length)) {
+ return -1;
+ }
+ predicate = getCallback(predicate, thisArg, 3);
+ return baseFindIndex(array, predicate, fromRight);
+ };
+ }
- /** Used to map characters to HTML entities. */
- var htmlEscapes = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '`': '`'
- };
+ /**
+ * Creates a `_.findKey` or `_.findLastKey` function.
+ *
+ * @private
+ * @param {Function} objectFunc The function to iterate over an object.
+ * @returns {Function} Returns the new find function.
+ */
+ function createFindKey(objectFunc) {
+ return function(object, predicate, thisArg) {
+ predicate = getCallback(predicate, thisArg, 3);
+ return baseFind(object, predicate, objectFunc, true);
+ };
+ }
- /** Used to map HTML entities to characters. */
- var htmlUnescapes = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- ''': "'",
- '`': '`'
- };
+ /**
+ * Creates a `_.flow` or `_.flowRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new flow function.
+ */
+ function createFlow(fromRight) {
+ return function() {
+ var length = arguments.length;
+ if (!length) {
+ return function() { return arguments[0]; };
+ }
+ var wrapper,
+ index = fromRight ? length : -1,
+ leftIndex = 0,
+ funcs = Array(length);
- /** Used to determine if values are of the language type `Object`. */
- var objectTypes = {
- 'function': true,
- 'object': true
- };
+ while ((fromRight ? index-- : ++index < length)) {
+ var func = funcs[leftIndex++] = arguments[index];
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var funcName = wrapper ? '' : getFuncName(func);
+ wrapper = funcName == 'wrapper' ? new LodashWrapper([]) : wrapper;
+ }
+ index = wrapper ? -1 : length;
+ while (++index < length) {
+ func = funcs[index];
+ funcName = getFuncName(func);
- /** Used to escape characters for inclusion in compiled string literals. */
- var stringEscapes = {
- '\\': '\\',
- "'": "'",
- '\n': 'n',
- '\r': 'r',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
+ var data = funcName == 'wrapper' ? getData(func) : null;
+ if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) {
+ wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
+ } else {
+ wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
+ }
+ }
+ return function() {
+ var args = arguments;
+ if (wrapper && args.length == 1 && isArray(args[0])) {
+ return wrapper.plant(args[0]).value();
+ }
+ var index = 0,
+ result = funcs[index].apply(this, args);
- /** Detect free variable `exports`. */
- var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+ while (++index < length) {
+ result = funcs[index].call(this, result);
+ }
+ return result;
+ };
+ };
+ }
- /** Detect free variable `module`. */
- var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+ /**
+ * Creates a function for `_.forEach` or `_.forEachRight`.
+ *
+ * @private
+ * @param {Function} arrayFunc The function to iterate over an array.
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @returns {Function} Returns the new each function.
+ */
+ function createForEach(arrayFunc, eachFunc) {
+ return function(collection, iteratee, thisArg) {
+ return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
+ ? arrayFunc(collection, iteratee)
+ : eachFunc(collection, bindCallback(iteratee, thisArg, 3));
+ };
+ }
- /** Detect free variable `global` from Node.js. */
- var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;
+ /**
+ * Creates a function for `_.forIn` or `_.forInRight`.
+ *
+ * @private
+ * @param {Function} objectFunc The function to iterate over an object.
+ * @returns {Function} Returns the new each function.
+ */
+ function createForIn(objectFunc) {
+ return function(object, iteratee, thisArg) {
+ if (typeof iteratee != 'function' || thisArg !== undefined) {
+ iteratee = bindCallback(iteratee, thisArg, 3);
+ }
+ return objectFunc(object, iteratee, keysIn);
+ };
+ }
- /** Detect free variable `self`. */
- var freeSelf = objectTypes[typeof self] && self && self.Object && self;
+ /**
+ * Creates a function for `_.forOwn` or `_.forOwnRight`.
+ *
+ * @private
+ * @param {Function} objectFunc The function to iterate over an object.
+ * @returns {Function} Returns the new each function.
+ */
+ function createForOwn(objectFunc) {
+ return function(object, iteratee, thisArg) {
+ if (typeof iteratee != 'function' || thisArg !== undefined) {
+ iteratee = bindCallback(iteratee, thisArg, 3);
+ }
+ return objectFunc(object, iteratee);
+ };
+ }
- /** Detect free variable `window`. */
- var freeWindow = objectTypes[typeof window] && window && window.Object && window;
-
- /** Detect the popular CommonJS extension `module.exports`. */
- var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
-
- /**
- * Used as a reference to the global object.
- *
- * The `this` value is used if it is the global object to avoid Greasemonkey's
- * restricted `window` object, otherwise the `window` object is used.
- */
- var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
-
- /*--------------------------------------------------------------------------*/
-
- /**
- * The base implementation of `compareAscending` which compares values and
- * sorts them in ascending order without guaranteeing a stable sort.
- *
- * @private
- * @param {*} value The value to compare to `other`.
- * @param {*} other The value to compare to `value`.
- * @returns {number} Returns the sort order indicator for `value`.
- */
- function baseCompareAscending(value, other) {
- if (value !== other) {
- var valIsReflexive = value === value,
- othIsReflexive = other === other;
+ /**
+ * Creates a function for `_.mapKeys` or `_.mapValues`.
+ *
+ * @private
+ * @param {boolean} [isMapKeys] Specify mapping keys instead of values.
+ * @returns {Function} Returns the new map function.
+ */
+ function createObjectMapper(isMapKeys) {
+ return function(object, iteratee, thisArg) {
+ var result = {};
+ iteratee = getCallback(iteratee, thisArg, 3);
- if (value > other || !valIsReflexive || (value === undefined && othIsReflexive)) {
- return 1;
- }
- if (value < other || !othIsReflexive || (other === undefined && valIsReflexive)) {
- return -1;
- }
+ baseForOwn(object, function(value, key, object) {
+ var mapped = iteratee(value, key, object);
+ key = isMapKeys ? mapped : key;
+ value = isMapKeys ? value : mapped;
+ result[key] = value;
+ });
+ return result;
+ };
}
- return 0;
- }
-
- /**
- * The base implementation of `_.findIndex` and `_.findLastIndex` without
- * support for callback shorthands and `this` binding.
- *
- * @private
- * @param {Array} array The array to search.
- * @param {Function} predicate The function invoked per iteration.
- * @param {boolean} [fromRight] Specify iterating from right to left.
- * @returns {number} Returns the index of the matched value, else `-1`.
- */
- function baseFindIndex(array, predicate, fromRight) {
- var length = array.length,
- index = fromRight ? length : -1;
- while ((fromRight ? index-- : ++index < length)) {
- if (predicate(array[index], index, array)) {
- return index;
- }
+ /**
+ * Creates a function for `_.padLeft` or `_.padRight`.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify padding from the right.
+ * @returns {Function} Returns the new pad function.
+ */
+ function createPadDir(fromRight) {
+ return function(string, length, chars) {
+ string = baseToString(string);
+ return (fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string);
+ };
}
- return -1;
- }
- /**
- * The base implementation of `_.indexOf` without support for binary searches.
- *
- * @private
- * @param {Array} array The array to search.
- * @param {*} value The value to search for.
- * @param {number} fromIndex The index to search from.
- * @returns {number} Returns the index of the matched value, else `-1`.
- */
- function baseIndexOf(array, value, fromIndex) {
- if (value !== value) {
- return indexOfNaN(array, fromIndex);
+ /**
+ * Creates a `_.partial` or `_.partialRight` function.
+ *
+ * @private
+ * @param {boolean} flag The partial bit flag.
+ * @returns {Function} Returns the new partial function.
+ */
+ function createPartial(flag) {
+ var partialFunc = restParam(function(func, partials) {
+ var holders = replaceHolders(partials, partialFunc.placeholder);
+ return createWrapper(func, flag, null, partials, holders);
+ });
+ return partialFunc;
}
- var index = fromIndex - 1,
- length = array.length;
- while (++index < length) {
- if (array[index] === value) {
- return index;
- }
+ /**
+ * Creates a function for `_.reduce` or `_.reduceRight`.
+ *
+ * @private
+ * @param {Function} arrayFunc The function to iterate over an array.
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @returns {Function} Returns the new each function.
+ */
+ function createReduce(arrayFunc, eachFunc) {
+ return function(collection, iteratee, accumulator, thisArg) {
+ var initFromArray = arguments.length < 3;
+ return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
+ ? arrayFunc(collection, iteratee, accumulator, initFromArray)
+ : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);
+ };
}
- return -1;
- }
- /**
- * The base implementation of `_.isFunction` without support for environments
- * with incorrect `typeof` results.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
- */
- function baseIsFunction(value) {
- // Avoid a Chakra JIT bug in compatibility modes of IE 11.
- // See https://github.com/jashkenas/underscore/issues/1621 for more details.
- return typeof value == 'function' || false;
- }
+ /**
+ * Creates a function that wraps `func` and invokes it with optional `this`
+ * binding of, partial application, and currying.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to reference.
+ * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to prepend to those provided to the new function.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [partialsRight] The arguments to append to those provided to the new function.
+ * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
+ var isAry = bitmask & ARY_FLAG,
+ isBind = bitmask & BIND_FLAG,
+ isBindKey = bitmask & BIND_KEY_FLAG,
+ isCurry = bitmask & CURRY_FLAG,
+ isCurryBound = bitmask & CURRY_BOUND_FLAG,
+ isCurryRight = bitmask & CURRY_RIGHT_FLAG;
- /**
- * Converts `value` to a string if it is not one. An empty string is returned
- * for `null` or `undefined` values.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
- function baseToString(value) {
- if (typeof value == 'string') {
- return value;
- }
- return value == null ? '' : (value + '');
- }
+ var Ctor = !isBindKey && createCtorWrapper(func),
+ key = func;
- /**
- * Used by `_.max` and `_.min` as the default callback for string values.
- *
- * @private
- * @param {string} string The string to inspect.
- * @returns {number} Returns the code unit of the first character of the string.
- */
- function charAtCallback(string) {
- return string.charCodeAt(0);
- }
+ function wrapper() {
+ // Avoid `arguments` object use disqualifying optimizations by
+ // converting it to an array before providing it to other functions.
+ var length = arguments.length,
+ index = length,
+ args = Array(length);
- /**
- * Used by `_.trim` and `_.trimLeft` to get the index of the first character
- * of `string` that is not found in `chars`.
- *
- * @private
- * @param {string} string The string to inspect.
- * @param {string} chars The characters to find.
- * @returns {number} Returns the index of the first character not found in `chars`.
- */
- function charsLeftIndex(string, chars) {
- var index = -1,
- length = string.length;
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ if (partials) {
+ args = composeArgs(args, partials, holders);
+ }
+ if (partialsRight) {
+ args = composeArgsRight(args, partialsRight, holdersRight);
+ }
+ if (isCurry || isCurryRight) {
+ var placeholder = wrapper.placeholder,
+ argsHolders = replaceHolders(args, placeholder);
- while (++index < length && chars.indexOf(string.charAt(index)) > -1) {}
- return index;
- }
+ length -= argsHolders.length;
+ if (length < arity) {
+ var newArgPos = argPos ? arrayCopy(argPos) : null,
+ newArity = nativeMax(arity - length, 0),
+ newsHolders = isCurry ? argsHolders : null,
+ newHoldersRight = isCurry ? null : argsHolders,
+ newPartials = isCurry ? args : null,
+ newPartialsRight = isCurry ? null : args;
- /**
- * Used by `_.trim` and `_.trimRight` to get the index of the last character
- * of `string` that is not found in `chars`.
- *
- * @private
- * @param {string} string The string to inspect.
- * @param {string} chars The characters to find.
- * @returns {number} Returns the index of the last character not found in `chars`.
- */
- function charsRightIndex(string, chars) {
- var index = string.length;
+ bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
+ bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
- while (index-- && chars.indexOf(string.charAt(index)) > -1) {}
- return index;
- }
+ if (!isCurryBound) {
+ bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
+ }
+ var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],
+ result = createHybridWrapper.apply(undefined, newData);
- /**
- * Used by `_.sortBy` to compare transformed elements of a collection and stable
- * sort them in ascending order.
- *
- * @private
- * @param {Object} object The object to compare to `other`.
- * @param {Object} other The object to compare to `object`.
- * @returns {number} Returns the sort order indicator for `object`.
- */
- function compareAscending(object, other) {
- return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index);
- }
-
- /**
- * Used by `_.sortByOrder` to compare multiple properties of each element
- * in a collection and stable sort them in the following order:
- *
- * If `orders` is unspecified, sort in ascending order for all properties.
- * Otherwise, for each property, sort in ascending order if its corresponding value in
- * orders is true, and descending order if false.
- *
- * @private
- * @param {Object} object The object to compare to `other`.
- * @param {Object} other The object to compare to `object`.
- * @param {boolean[]} orders The order to sort by for each property.
- * @returns {number} Returns the sort order indicator for `object`.
- */
- function compareMultiple(object, other, orders) {
- var index = -1,
- objCriteria = object.criteria,
- othCriteria = other.criteria,
- length = objCriteria.length,
- ordersLength = orders.length;
-
- while (++index < length) {
- var result = baseCompareAscending(objCriteria[index], othCriteria[index]);
- if (result) {
- if (index >= ordersLength) {
- return result;
+ if (isLaziable(func)) {
+ setData(result, newData);
+ }
+ result.placeholder = placeholder;
+ return result;
+ }
}
- return result * (orders[index] ? 1 : -1);
+ var thisBinding = isBind ? thisArg : this;
+ if (isBindKey) {
+ func = thisBinding[key];
+ }
+ if (argPos) {
+ args = reorder(args, argPos);
+ }
+ if (isAry && ary < args.length) {
+ args.length = ary;
+ }
+ var fn = (this && this !== root && this instanceof wrapper) ? (Ctor || createCtorWrapper(func)) : func;
+ return fn.apply(thisBinding, args);
}
+ return wrapper;
}
- // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
- // that causes it, under certain circumstances, to provide the same value for
- // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
- // for more details.
- //
- // This also ensures a stable sort in V8 and other engines.
- // See https://code.google.com/p/v8/issues/detail?id=90 for more details.
- return object.index - other.index;
- }
-
- /**
- * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
- *
- * @private
- * @param {string} letter The matched letter to deburr.
- * @returns {string} Returns the deburred letter.
- */
- function deburrLetter(letter) {
- return deburredLetters[letter];
- }
-
- /**
- * Used by `_.escape` to convert characters to HTML entities.
- *
- * @private
- * @param {string} chr The matched character to escape.
- * @returns {string} Returns the escaped character.
- */
- function escapeHtmlChar(chr) {
- return htmlEscapes[chr];
- }
-
- /**
- * Used by `_.template` to escape characters for inclusion in compiled
- * string literals.
- *
- * @private
- * @param {string} chr The matched character to escape.
- * @returns {string} Returns the escaped character.
- */
- function escapeStringChar(chr) {
- return '\\' + stringEscapes[chr];
- }
- /**
- * Gets the index at which the first occurrence of `NaN` is found in `array`.
- *
- * @private
- * @param {Array} array The array to search.
- * @param {number} fromIndex The index to search from.
- * @param {boolean} [fromRight] Specify iterating from right to left.
- * @returns {number} Returns the index of the matched `NaN`, else `-1`.
- */
- function indexOfNaN(array, fromIndex, fromRight) {
- var length = array.length,
- index = fromIndex + (fromRight ? 0 : -1);
+ /**
+ * Creates the padding required for `string` based on the given `length`.
+ * The `chars` string is truncated if the number of characters exceeds `length`.
+ *
+ * @private
+ * @param {string} string The string to create padding for.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the pad for `string`.
+ */
+ function createPadding(string, length, chars) {
+ var strLength = string.length;
+ length = +length;
- while ((fromRight ? index-- : ++index < length)) {
- var other = array[index];
- if (other !== other) {
- return index;
+ if (strLength >= length || !nativeIsFinite(length)) {
+ return '';
}
+ var padLength = length - strLength;
+ chars = chars == null ? ' ' : (chars + '');
+ return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength);
}
- return -1;
- }
-
- /**
- * Checks if `value` is object-like.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
- */
- function isObjectLike(value) {
- return !!value && typeof value == 'object';
- }
- /**
- * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a
- * character code is whitespace.
- *
- * @private
- * @param {number} charCode The character code to inspect.
- * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`.
- */
- function isSpace(charCode) {
- return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 ||
- (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279)));
- }
+ /**
+ * Creates a function that wraps `func` and invokes it with the optional `this`
+ * binding of `thisArg` and the `partials` prepended to those provided to
+ * the wrapper.
+ *
+ * @private
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} partials The arguments to prepend to those provided to the new function.
+ * @returns {Function} Returns the new bound function.
+ */
+ function createPartialWrapper(func, bitmask, thisArg, partials) {
+ var isBind = bitmask & BIND_FLAG,
+ Ctor = createCtorWrapper(func);
- /**
- * Replaces all `placeholder` elements in `array` with an internal placeholder
- * and returns an array of their indexes.
- *
- * @private
- * @param {Array} array The array to modify.
- * @param {*} placeholder The placeholder to replace.
- * @returns {Array} Returns the new array of placeholder indexes.
- */
- function replaceHolders(array, placeholder) {
- var index = -1,
- length = array.length,
- resIndex = -1,
- result = [];
+ function wrapper() {
+ // Avoid `arguments` object use disqualifying optimizations by
+ // converting it to an array before providing it `func`.
+ var argsIndex = -1,
+ argsLength = arguments.length,
+ leftIndex = -1,
+ leftLength = partials.length,
+ args = Array(argsLength + leftLength);
- while (++index < length) {
- if (array[index] === placeholder) {
- array[index] = PLACEHOLDER;
- result[++resIndex] = index;
+ while (++leftIndex < leftLength) {
+ args[leftIndex] = partials[leftIndex];
+ }
+ while (argsLength--) {
+ args[leftIndex++] = arguments[++argsIndex];
+ }
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return fn.apply(isBind ? thisArg : this, args);
}
+ return wrapper;
}
- return result;
- }
-
- /**
- * An implementation of `_.uniq` optimized for sorted arrays without support
- * for callback shorthands and `this` binding.
- *
- * @private
- * @param {Array} array The array to inspect.
- * @param {Function} [iteratee] The function invoked per iteration.
- * @returns {Array} Returns the new duplicate-value-free array.
- */
- function sortedUniq(array, iteratee) {
- var seen,
- index = -1,
- length = array.length,
- resIndex = -1,
- result = [];
-
- while (++index < length) {
- var value = array[index],
- computed = iteratee ? iteratee(value, index, array) : value;
- if (!index || seen !== computed) {
- seen = computed;
- result[++resIndex] = value;
- }
+ /**
+ * Creates a `_.sortedIndex` or `_.sortedLastIndex` function.
+ *
+ * @private
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {Function} Returns the new index function.
+ */
+ function createSortedIndex(retHighest) {
+ return function(array, value, iteratee, thisArg) {
+ var func = getCallback(iteratee);
+ return (func === baseCallback && iteratee == null)
+ ? binaryIndex(array, value, retHighest)
+ : binaryIndexBy(array, value, func(iteratee, thisArg, 1), retHighest);
+ };
}
- return result;
- }
- /**
- * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace
- * character of `string`.
- *
- * @private
- * @param {string} string The string to inspect.
- * @returns {number} Returns the index of the first non-whitespace character.
- */
- function trimmedLeftIndex(string) {
- var index = -1,
- length = string.length;
-
- while (++index < length && isSpace(string.charCodeAt(index))) {}
- return index;
- }
-
- /**
- * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace
- * character of `string`.
- *
- * @private
- * @param {string} string The string to inspect.
- * @returns {number} Returns the index of the last non-whitespace character.
- */
- function trimmedRightIndex(string) {
- var index = string.length;
+ /**
+ * Creates a function that either curries or invokes `func` with optional
+ * `this` binding and partially applied arguments.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to reference.
+ * @param {number} bitmask The bitmask of flags.
+ * The bitmask may be composed of the following flags:
+ * 1 - `_.bind`
+ * 2 - `_.bindKey`
+ * 4 - `_.curry` or `_.curryRight` of a bound function
+ * 8 - `_.curry`
+ * 16 - `_.curryRight`
+ * 32 - `_.partial`
+ * 64 - `_.partialRight`
+ * 128 - `_.rearg`
+ * 256 - `_.ary`
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to be partially applied.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
+ var isBindKey = bitmask & BIND_KEY_FLAG;
+ if (!isBindKey && typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var length = partials ? partials.length : 0;
+ if (!length) {
+ bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
+ partials = holders = null;
+ }
+ length -= (holders ? holders.length : 0);
+ if (bitmask & PARTIAL_RIGHT_FLAG) {
+ var partialsRight = partials,
+ holdersRight = holders;
- while (index-- && isSpace(string.charCodeAt(index))) {}
- return index;
- }
+ partials = holders = null;
+ }
+ var data = isBindKey ? null : getData(func),
+ newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
- /**
- * Used by `_.unescape` to convert HTML entities to characters.
- *
- * @private
- * @param {string} chr The matched character to unescape.
- * @returns {string} Returns the unescaped character.
- */
- function unescapeHtmlChar(chr) {
- return htmlUnescapes[chr];
- }
+ if (data) {
+ mergeData(newData, data);
+ bitmask = newData[1];
+ arity = newData[9];
+ }
+ newData[9] = arity == null
+ ? (isBindKey ? 0 : func.length)
+ : (nativeMax(arity - length, 0) || 0);
- /*--------------------------------------------------------------------------*/
+ if (bitmask == BIND_FLAG) {
+ var result = createBindWrapper(newData[0], newData[2]);
+ } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {
+ result = createPartialWrapper.apply(undefined, newData);
+ } else {
+ result = createHybridWrapper.apply(undefined, newData);
+ }
+ var setter = data ? baseSetData : setData;
+ return setter(result, newData);
+ }
- /**
- * Create a new pristine `lodash` function using the given `context` object.
- *
- * @static
- * @memberOf _
- * @category Utility
- * @param {Object} [context=root] The context object.
- * @returns {Function} Returns a new `lodash` function.
- * @example
- *
- * _.mixin({ 'foo': _.constant('foo') });
- *
- * var lodash = _.runInContext();
- * lodash.mixin({ 'bar': lodash.constant('bar') });
- *
- * _.isFunction(_.foo);
- * // => true
- * _.isFunction(_.bar);
- * // => false
- *
- * lodash.isFunction(lodash.foo);
- * // => false
- * lodash.isFunction(lodash.bar);
- * // => true
- *
- * // using `context` to mock `Date#getTime` use in `_.now`
- * var mock = _.runInContext({
- * 'Date': function() {
- * return { 'getTime': getTimeMock };
- * }
- * });
- *
- * // or creating a suped-up `defer` in Node.js
- * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
- */
- function runInContext(context) {
- // Avoid issues with some ES3 environments that attempt to use values, named
- // after built-in constructors like `Object`, for the creation of literals.
- // ES5 clears this up by stating that literals must use built-in constructors.
- // See https://es5.github.io/#x11.1.5 for more details.
- context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
+ /**
+ * A specialized version of `baseIsEqualDeep` for arrays with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Array} array The array to compare.
+ * @param {Array} other The other array to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparing arrays.
+ * @param {boolean} [isLoose] Specify performing partial comparisons.
+ * @param {Array} [stackA] Tracks traversed `value` objects.
+ * @param {Array} [stackB] Tracks traversed `other` objects.
+ * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
+ */
+ function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
+ var index = -1,
+ arrLength = array.length,
+ othLength = other.length,
+ result = true;
- /** Native constructor references. */
- var Array = context.Array,
- Date = context.Date,
- Error = context.Error,
- Function = context.Function,
- Math = context.Math,
- Number = context.Number,
- Object = context.Object,
- RegExp = context.RegExp,
- String = context.String,
- TypeError = context.TypeError;
+ if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
+ return false;
+ }
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (result && ++index < arrLength) {
+ var arrValue = array[index],
+ othValue = other[index];
- /** Used for native method references. */
- var arrayProto = Array.prototype,
- objectProto = Object.prototype,
- stringProto = String.prototype;
+ result = undefined;
+ if (customizer) {
+ result = isLoose
+ ? customizer(othValue, arrValue, index)
+ : customizer(arrValue, othValue, index);
+ }
+ if (result === undefined) {
+ // Recursively compare arrays (susceptible to call stack limits).
+ if (isLoose) {
+ var othIndex = othLength;
+ while (othIndex--) {
+ othValue = other[othIndex];
+ result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
+ if (result) {
+ break;
+ }
+ }
+ } else {
+ result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
+ }
+ }
+ }
+ return !!result;
+ }
- /** Used to detect DOM support. */
- var document = (document = context.window) && document.document;
+ /**
+ * A specialized version of `baseIsEqualDeep` for comparing objects of
+ * the same `toStringTag`.
+ *
+ * **Note:** This function only supports comparing values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} value The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {string} tag The `toStringTag` of the objects to compare.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalByTag(object, other, tag) {
+ switch (tag) {
+ case boolTag:
+ case dateTag:
+ // Coerce dates and booleans to numbers, dates to milliseconds and booleans
+ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
+ return +object == +other;
- /** Used to resolve the decompiled source of functions. */
- var fnToString = Function.prototype.toString;
+ case errorTag:
+ return object.name == other.name && object.message == other.message;
- /** Used to check objects for own properties. */
- var hasOwnProperty = objectProto.hasOwnProperty;
+ case numberTag:
+ // Treat `NaN` vs. `NaN` as equal.
+ return (object != +object)
+ ? other != +other
+ : object == +other;
- /** Used to generate unique IDs. */
- var idCounter = 0;
+ case regexpTag:
+ case stringTag:
+ // Coerce regexes to strings and treat strings primitives and string
+ // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
+ return object == (other + '');
+ }
+ return false;
+ }
/**
- * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
- * of values.
+ * A specialized version of `baseIsEqualDeep` for objects with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparing values.
+ * @param {boolean} [isLoose] Specify performing partial comparisons.
+ * @param {Array} [stackA] Tracks traversed `value` objects.
+ * @param {Array} [stackB] Tracks traversed `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
*/
- var objToString = objectProto.toString;
-
- /** Used to restore the original `_` reference in `_.noConflict`. */
- var oldDash = context._;
-
- /** Used to detect if a method is native. */
- var reIsNative = RegExp('^' +
- escapeRegExp(objToString)
- .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
- );
-
- /** Native method references. */
- var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer,
- bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice,
- ceil = Math.ceil,
- clearTimeout = context.clearTimeout,
- floor = Math.floor,
- getOwnPropertySymbols = isNative(getOwnPropertySymbols = Object.getOwnPropertySymbols) && getOwnPropertySymbols,
- getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
- push = arrayProto.push,
- preventExtensions = isNative(Object.preventExtensions = Object.preventExtensions) && preventExtensions,
- propertyIsEnumerable = objectProto.propertyIsEnumerable,
- Set = isNative(Set = context.Set) && Set,
- setTimeout = context.setTimeout,
- splice = arrayProto.splice,
- Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array,
- WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap;
-
- /** Used to clone array buffers. */
- var Float64Array = (function() {
- // Safari 5 errors when using an array buffer to initialize a typed array
- // where the array buffer's `byteLength` is not a multiple of the typed
- // array's `BYTES_PER_ELEMENT`.
- try {
- var func = isNative(func = context.Float64Array) && func,
- result = new func(new ArrayBuffer(10), 0, 1) && func;
- } catch(e) {}
- return result;
- }());
-
- /** Used as `baseAssign`. */
- var nativeAssign = (function() {
- // Avoid `Object.assign` in Firefox 34-37 which have an early implementation
- // with a now defunct try/catch behavior. See https://bugzilla.mozilla.org/show_bug.cgi?id=1103344
- // for more details.
- //
- // Use `Object.preventExtensions` on a plain object instead of simply using
- // `Object('x')` because Chrome and IE fail to throw an error when attempting
- // to assign values to readonly indexes of strings in strict mode.
- var object = { '1': 0 },
- func = preventExtensions && isNative(func = Object.assign) && func;
-
- try { func(preventExtensions(object), 'xo'); } catch(e) {}
- return !object[1] && func;
- }());
-
- /* Native method references for those with the same name as other `lodash` methods. */
- var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
- nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
- nativeIsFinite = context.isFinite,
- nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
- nativeMax = Math.max,
- nativeMin = Math.min,
- nativeNow = isNative(nativeNow = Date.now) && nativeNow,
- nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite,
- nativeParseInt = context.parseInt,
- nativeRandom = Math.random;
-
- /** Used as references for `-Infinity` and `Infinity`. */
- var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY,
- POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
-
- /** Used as references for the maximum length and index of an array. */
- var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1,
- MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
- HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
+ function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
+ var objProps = keys(object),
+ objLength = objProps.length,
+ othProps = keys(other),
+ othLength = othProps.length;
- /** Used as the size, in bytes, of each `Float64Array` element. */
- var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0;
+ if (objLength != othLength && !isLoose) {
+ return false;
+ }
+ var skipCtor = isLoose,
+ index = -1;
- /**
- * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
- * of an array-like value.
- */
- var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
+ while (++index < objLength) {
+ var key = objProps[index],
+ result = isLoose ? key in other : hasOwnProperty.call(other, key);
- /** Used to store function metadata. */
- var metaMap = WeakMap && new WeakMap;
+ if (result) {
+ var objValue = object[key],
+ othValue = other[key];
- /** Used to lookup unminified function names. */
- var realNames = {};
+ result = undefined;
+ if (customizer) {
+ result = isLoose
+ ? customizer(othValue, objValue, key)
+ : customizer(objValue, othValue, key);
+ }
+ if (result === undefined) {
+ // Recursively compare objects (susceptible to call stack limits).
+ result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB);
+ }
+ }
+ if (!result) {
+ return false;
+ }
+ skipCtor || (skipCtor = key == 'constructor');
+ }
+ if (!skipCtor) {
+ var objCtor = object.constructor,
+ othCtor = other.constructor;
- /*------------------------------------------------------------------------*/
+ // Non `Object` object instances with different constructors are not equal.
+ if (objCtor != othCtor &&
+ ('constructor' in object && 'constructor' in other) &&
+ !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
+ typeof othCtor == 'function' && othCtor instanceof othCtor)) {
+ return false;
+ }
+ }
+ return true;
+ }
/**
- * Creates a `lodash` object which wraps `value` to enable implicit chaining.
- * Methods that operate on and return arrays, collections, and functions can
- * be chained together. Methods that return a boolean or single value will
- * automatically end the chain returning the unwrapped value. Explicit chaining
- * may be enabled using `_.chain`. The execution of chained methods is lazy,
- * that is, execution is deferred until `_#value` is implicitly or explicitly
- * called.
- *
- * Lazy evaluation allows several methods to support shortcut fusion. Shortcut
- * fusion is an optimization that merges iteratees to avoid creating intermediate
- * arrays and reduce the number of iteratee executions.
- *
- * Chaining is supported in custom builds as long as the `_#value` method is
- * directly or indirectly included in the build.
- *
- * In addition to lodash methods, wrappers have `Array` and `String` methods.
- *
- * The wrapper `Array` methods are:
- * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`,
- * `splice`, and `unshift`
- *
- * The wrapper `String` methods are:
- * `replace` and `split`
- *
- * The wrapper methods that support shortcut fusion are:
- * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,
- * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`,
- * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`,
- * and `where`
- *
- * The chainable wrapper methods are:
- * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`,
- * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`,
- * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`,
- * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`,
- * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`,
- * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`,
- * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`,
- * `keysIn`, `map`, `mapValues`, `matches`, `matchesProperty`, `memoize`,
- * `merge`, `mixin`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
- * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`,
- * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `reverse`,
- * `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`,
- * `spread`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`,
- * `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, `transform`,
- * `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, `where`,
- * `without`, `wrap`, `xor`, `zip`, and `zipObject`
- *
- * The wrapper methods that are **not** chainable by default are:
- * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`,
- * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`,
- * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`,
- * `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, `isArray`,
- * `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`
- * `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`,
- * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `isTypedArray`,
- * `join`, `kebabCase`, `last`, `lastIndexOf`, `max`, `min`, `noConflict`,
- * `noop`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`,
- * `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, `shift`, `size`,
- * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, `startsWith`,
- * `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, `unescape`,
- * `uniqueId`, `value`, and `words`
- *
- * The wrapper method `sample` will return a wrapped value when `n` is provided,
- * otherwise an unwrapped value is returned.
- *
- * @name _
- * @constructor
- * @category Chain
- * @param {*} value The value to wrap in a `lodash` instance.
- * @returns {Object} Returns the new `lodash` wrapper instance.
- * @example
- *
- * var wrapped = _([1, 2, 3]);
- *
- * // returns an unwrapped value
- * wrapped.reduce(function(total, n) {
- * return total + n;
- * });
- * // => 6
- *
- * // returns a wrapped value
- * var squares = wrapped.map(function(n) {
- * return n * n;
- * });
- *
- * _.isArray(squares);
- * // => false
+ * Gets the extremum value of `collection` invoking `iteratee` for each value
+ * in `collection` to generate the criterion by which the value is ranked.
+ * The `iteratee` is invoked with three arguments: (value, index, collection).
*
- * _.isArray(squares.value());
- * // => true
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {boolean} [isMin] Specify returning the minimum, instead of the
+ * maximum, extremum value.
+ * @returns {*} Returns the extremum value.
*/
- function lodash(value) {
- if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
- if (value instanceof LodashWrapper) {
- return value;
- }
- if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {
- return wrapperClone(value);
+ function extremumBy(collection, iteratee, isMin) {
+ var exValue = isMin ? POSITIVE_INFINITY : NEGATIVE_INFINITY,
+ computed = exValue,
+ result = computed;
+
+ baseEach(collection, function(value, index, collection) {
+ var current = iteratee(value, index, collection);
+ if ((isMin ? (current < computed) : (current > computed)) ||
+ (current === exValue && current === result)) {
+ computed = current;
+ result = value;
}
- }
- return new LodashWrapper(value);
+ });
+ return result;
}
/**
- * The function whose prototype all chaining wrappers inherit from.
+ * Gets the appropriate "callback" function. If the `_.callback` method is
+ * customized this function returns the custom method, otherwise it returns
+ * the `baseCallback` function. If arguments are provided the chosen function
+ * is invoked with them and its result is returned.
*
* @private
+ * @returns {Function} Returns the chosen function or its result.
*/
- function baseLodash() {
- // No operation performed.
+ function getCallback(func, thisArg, argCount) {
+ var result = lodash.callback || callback;
+ result = result === callback ? baseCallback : result;
+ return argCount ? result(func, thisArg, argCount) : result;
}
/**
- * The base constructor for creating `lodash` wrapper objects.
+ * Gets metadata for `func`.
*
* @private
- * @param {*} value The value to wrap.
- * @param {boolean} [chainAll] Enable chaining for all wrapper methods.
- * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value.
+ * @param {Function} func The function to query.
+ * @returns {*} Returns the metadata for `func`.
*/
- function LodashWrapper(value, chainAll, actions) {
- this.__wrapped__ = value;
- this.__actions__ = actions || [];
- this.__chain__ = !!chainAll;
- }
+ var getData = !metaMap ? noop : function(func) {
+ return metaMap.get(func);
+ };
/**
- * An object environment feature flags.
+ * Gets the name of `func`.
*
- * @static
- * @memberOf _
- * @type Object
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {string} Returns the function name.
*/
- var support = lodash.support = {};
-
- (function(x) {
- var Ctor = function() { this.x = x; },
- object = { '0': x, 'length': x },
- props = [];
-
- Ctor.prototype = { 'valueOf': x, 'y': x };
- for (var key in new Ctor) { props.push(key); }
-
- /**
- * Detect if functions can be decompiled by `Function#toString`
- * (all but Firefox OS certified apps, older Opera mobile browsers, and
- * the PlayStation 3; forced `false` for Windows 8 apps).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.funcDecomp = /\bthis\b/.test(function() { return this; });
-
- /**
- * Detect if `Function#name` is supported (all but IE).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.funcNames = typeof Function.name == 'string';
-
- /**
- * Detect if the DOM is supported.
- *
- * @memberOf _.support
- * @type boolean
- */
- try {
- support.dom = document.createDocumentFragment().nodeType === 11;
- } catch(e) {
- support.dom = false;
+ var getFuncName = (function() {
+ if (!support.funcNames) {
+ return constant('');
}
-
- /**
- * Detect if `arguments` object indexes are non-enumerable.
- *
- * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object
- * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat
- * `arguments` object indexes as non-enumerable and fail `hasOwnProperty`
- * checks for indexes that exceed the number of function parameters and
- * whose associated argument values are `0`.
- *
- * @memberOf _.support
- * @type boolean
- */
- try {
- support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1);
- } catch(e) {
- support.nonEnumArgs = true;
+ if (constant.name == 'constant') {
+ return baseProperty('name');
}
- }(1, 0));
+ return function(func) {
+ var result = func.name,
+ array = realNames[result],
+ length = array ? array.length : 0;
+
+ while (length--) {
+ var data = array[length],
+ otherFunc = data.func;
+
+ if (otherFunc == null || otherFunc == func) {
+ return data.name;
+ }
+ }
+ return result;
+ };
+ }());
/**
- * By default, the template delimiters used by lodash are like those in
- * embedded Ruby (ERB). Change the following template settings to use
- * alternative delimiters.
+ * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
+ * customized this function returns the custom method, otherwise it returns
+ * the `baseIndexOf` function. If arguments are provided the chosen function
+ * is invoked with them and its result is returned.
*
- * @static
- * @memberOf _
- * @type Object
+ * @private
+ * @returns {Function|number} Returns the chosen function or its result.
*/
- lodash.templateSettings = {
-
- /**
- * Used to detect `data` property values to be HTML-escaped.
- *
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'escape': reEscape,
-
- /**
- * Used to detect code to be evaluated.
- *
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'evaluate': reEvaluate,
-
- /**
- * Used to detect `data` property values to inject.
- *
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'interpolate': reInterpolate,
-
- /**
- * Used to reference the data object in the template text.
- *
- * @memberOf _.templateSettings
- * @type string
- */
- 'variable': '',
-
- /**
- * Used to import variables into the compiled template.
- *
- * @memberOf _.templateSettings
- * @type Object
- */
- 'imports': {
-
- /**
- * A reference to the `lodash` function.
- *
- * @memberOf _.templateSettings.imports
- * @type Function
- */
- '_': lodash
- }
- };
+ function getIndexOf(collection, target, fromIndex) {
+ var result = lodash.indexOf || indexOf;
+ result = result === indexOf ? baseIndexOf : result;
+ return collection ? result(collection, target, fromIndex) : result;
+ }
- /*------------------------------------------------------------------------*/
+ /**
+ * Gets the "length" property value of `object`.
+ *
+ * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
+ * that affects Safari on at least iOS 8.1-8.3 ARM64.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {*} Returns the "length" value.
+ */
+ var getLength = baseProperty('length');
/**
- * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
+ * Creates an array of the own symbols of `object`.
*
* @private
- * @param {*} value The value to wrap.
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
*/
- function LazyWrapper(value) {
- this.__wrapped__ = value;
- this.__actions__ = null;
- this.__dir__ = 1;
- this.__dropCount__ = 0;
- this.__filtered__ = false;
- this.__iteratees__ = null;
- this.__takeCount__ = POSITIVE_INFINITY;
- this.__views__ = null;
- }
+ var getSymbols = !getOwnPropertySymbols ? constant([]) : function(object) {
+ return getOwnPropertySymbols(toObject(object));
+ };
/**
- * Creates a clone of the lazy wrapper object.
+ * Gets the view, applying any `transforms` to the `start` and `end` positions.
*
* @private
- * @name clone
- * @memberOf LazyWrapper
- * @returns {Object} Returns the cloned `LazyWrapper` object.
+ * @param {number} start The start of the view.
+ * @param {number} end The end of the view.
+ * @param {Array} [transforms] The transformations to apply to the view.
+ * @returns {Object} Returns an object containing the `start` and `end`
+ * positions of the view.
*/
- function lazyClone() {
- var actions = this.__actions__,
- iteratees = this.__iteratees__,
- views = this.__views__,
- result = new LazyWrapper(this.__wrapped__);
+ function getView(start, end, transforms) {
+ var index = -1,
+ length = transforms ? transforms.length : 0;
- result.__actions__ = actions ? arrayCopy(actions) : null;
- result.__dir__ = this.__dir__;
- result.__filtered__ = this.__filtered__;
- result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null;
- result.__takeCount__ = this.__takeCount__;
- result.__views__ = views ? arrayCopy(views) : null;
- return result;
+ while (++index < length) {
+ var data = transforms[index],
+ size = data.size;
+
+ switch (data.type) {
+ case 'drop': start += size; break;
+ case 'dropRight': end -= size; break;
+ case 'take': end = nativeMin(end, start + size); break;
+ case 'takeRight': start = nativeMax(start, end - size); break;
+ }
+ }
+ return { 'start': start, 'end': end };
}
/**
- * Reverses the direction of lazy iteration.
+ * Initializes an array clone.
*
* @private
- * @name reverse
- * @memberOf LazyWrapper
- * @returns {Object} Returns the new reversed `LazyWrapper` object.
+ * @param {Array} array The array to clone.
+ * @returns {Array} Returns the initialized clone.
*/
- function lazyReverse() {
- if (this.__filtered__) {
- var result = new LazyWrapper(this);
- result.__dir__ = -1;
- result.__filtered__ = true;
- } else {
- result = this.clone();
- result.__dir__ *= -1;
+ function initCloneArray(array) {
+ var length = array.length,
+ result = new array.constructor(length);
+
+ // Add array properties assigned by `RegExp#exec`.
+ if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
+ result.index = array.index;
+ result.input = array.input;
}
return result;
}
/**
- * Extracts the unwrapped value from its lazy wrapper.
+ * Initializes an object clone.
*
* @private
- * @name value
- * @memberOf LazyWrapper
- * @returns {*} Returns the unwrapped value.
+ * @param {Object} object The object to clone.
+ * @returns {Object} Returns the initialized clone.
*/
- function lazyValue() {
- var array = this.__wrapped__.value();
- if (!isArray(array)) {
- return baseWrapperValue(array, this.__actions__);
+ function initCloneObject(object) {
+ var Ctor = object.constructor;
+ if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
+ Ctor = Object;
}
- var dir = this.__dir__,
- isRight = dir < 0,
- view = getView(0, array.length, this.__views__),
- start = view.start,
- end = view.end,
- length = end - start,
- index = isRight ? end : (start - 1),
- takeCount = nativeMin(length, this.__takeCount__),
- iteratees = this.__iteratees__,
- iterLength = iteratees ? iteratees.length : 0,
- resIndex = 0,
- result = [];
+ return new Ctor;
+ }
- outer:
- while (length-- && resIndex < takeCount) {
- index += dir;
+ /**
+ * Initializes an object clone based on its `toStringTag`.
+ *
+ * **Note:** This function only supports cloning values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @param {string} tag The `toStringTag` of the object to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneByTag(object, tag, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return bufferClone(object);
- var iterIndex = -1,
- value = array[index];
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
- while (++iterIndex < iterLength) {
- var data = iteratees[iterIndex],
- iteratee = data.iteratee,
- type = data.type;
+ case float32Tag: case float64Tag:
+ case int8Tag: case int16Tag: case int32Tag:
+ case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
+ var buffer = object.buffer;
+ return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
- if (type == LAZY_DROP_WHILE_FLAG) {
- if (data.done && (isRight ? (index > data.index) : (index < data.index))) {
- data.count = 0;
- data.done = false;
- }
- data.index = index;
- if (!data.done) {
- var limit = data.limit;
- if (!(data.done = limit > -1 ? (data.count++ >= limit) : !iteratee(value))) {
- continue outer;
- }
- }
- } else {
- var computed = iteratee(value);
- if (type == LAZY_MAP_FLAG) {
- value = computed;
- } else if (!computed) {
- if (type == LAZY_FILTER_FLAG) {
- continue outer;
- } else {
- break outer;
- }
- }
- }
- }
- result[resIndex++] = value;
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+
+ case regexpTag:
+ var result = new Ctor(object.source, reFlags.exec(object));
+ result.lastIndex = object.lastIndex;
}
return result;
}
- /*------------------------------------------------------------------------*/
-
/**
- * Creates a cache object to store key/value pairs.
+ * Invokes the method at `path` on `object`.
*
* @private
- * @static
- * @name Cache
- * @memberOf _.memoize
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {Array} args The arguments to invoke the method with.
+ * @returns {*} Returns the result of the invoked method.
*/
- function MapCache() {
- this.__data__ = {};
+ function invokePath(object, path, args) {
+ if (object != null && !isKey(path, object)) {
+ path = toPath(path);
+ object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+ path = last(path);
+ }
+ var func = object == null ? object : object[path];
+ return func == null ? undefined : func.apply(object, args);
}
/**
- * Removes `key` and its value from the cache.
+ * Checks if `value` is array-like.
*
* @private
- * @name delete
- * @memberOf _.memoize.Cache
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
*/
- function mapDelete(key) {
- return this.has(key) && delete this.__data__[key];
+ function isArrayLike(value) {
+ return value != null && isLength(getLength(value));
}
/**
- * Gets the cached value for `key`.
+ * Checks if `value` is a valid array-like index.
*
* @private
- * @name get
- * @memberOf _.memoize.Cache
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the cached value.
+ * @param {*} value The value to check.
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
*/
- function mapGet(key) {
- return key == '__proto__' ? undefined : this.__data__[key];
+ function isIndex(value, length) {
+ value = +value;
+ length = length == null ? MAX_SAFE_INTEGER : length;
+ return value > -1 && value % 1 == 0 && value < length;
}
/**
- * Checks if a cached value for `key` exists.
+ * Checks if the provided arguments are from an iteratee call.
*
* @private
- * @name has
- * @memberOf _.memoize.Cache
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ * @param {*} value The potential iteratee value argument.
+ * @param {*} index The potential iteratee index or key argument.
+ * @param {*} object The potential iteratee object argument.
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
*/
- function mapHas(key) {
- return key != '__proto__' && hasOwnProperty.call(this.__data__, key);
+ function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == 'number'
+ ? (isArrayLike(object) && isIndex(index, object.length))
+ : (type == 'string' && index in object)) {
+ var other = object[index];
+ return value === value ? (value === other) : (other !== other);
+ }
+ return false;
}
/**
- * Sets `value` to `key` of the cache.
+ * Checks if `value` is a property name and not a property path.
*
* @private
- * @name set
- * @memberOf _.memoize.Cache
- * @param {string} key The key of the value to cache.
- * @param {*} value The value to cache.
- * @returns {Object} Returns the cache object.
+ * @param {*} value The value to check.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
*/
- function mapSet(key, value) {
- if (key != '__proto__') {
- this.__data__[key] = value;
+ function isKey(value, object) {
+ var type = typeof value;
+ if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
+ return true;
}
- return this;
+ if (isArray(value)) {
+ return false;
+ }
+ var result = !reIsDeepProp.test(value);
+ return result || (object != null && value in toObject(object));
}
- /*------------------------------------------------------------------------*/
-
/**
- *
- * Creates a cache object to store unique values.
+ * Checks if `func` has a lazy counterpart.
*
* @private
- * @param {Array} [values] The values to cache.
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.
*/
- function SetCache(values) {
- var length = values ? values.length : 0;
-
- this.data = { 'hash': nativeCreate(null), 'set': new Set };
- while (length--) {
- this.push(values[length]);
- }
+ function isLaziable(func) {
+ var funcName = getFuncName(func);
+ return !!funcName && func === lodash[funcName] && funcName in LazyWrapper.prototype;
}
/**
- * Checks if `value` is in `cache` mimicking the return signature of
- * `_.indexOf` by returning `0` if the value is found, else `-1`.
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
*
* @private
- * @param {Object} cache The cache to search.
- * @param {*} value The value to search for.
- * @returns {number} Returns `0` if `value` is found, else `-1`.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
*/
- function cacheIndexOf(cache, value) {
- var data = cache.data,
- result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value];
-
- return result ? 0 : -1;
+ function isLength(value) {
+ return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}
/**
- * Adds `value` to the cache.
+ * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
*
* @private
- * @name push
- * @memberOf SetCache
- * @param {*} value The value to cache.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` if suitable for strict
+ * equality comparisons, else `false`.
*/
- function cachePush(value) {
- var data = this.data;
- if (typeof value == 'string' || isObject(value)) {
- data.set.add(value);
- } else {
- data.hash[value] = true;
- }
+ function isStrictComparable(value) {
+ return value === value && !isObject(value);
}
- /*------------------------------------------------------------------------*/
-
/**
- * Copies the values of `source` to `array`.
+ * Merges the function metadata of `source` into `data`.
+ *
+ * Merging metadata reduces the number of wrappers required to invoke a function.
+ * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
+ * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`
+ * augment function arguments, making the order in which they are executed important,
+ * preventing the merging of metadata. However, we make an exception for a safe
+ * common case where curried functions have `_.ary` and or `_.rearg` applied.
*
* @private
- * @param {Array} source The array to copy values from.
- * @param {Array} [array=[]] The array to copy values to.
- * @returns {Array} Returns `array`.
+ * @param {Array} data The destination metadata.
+ * @param {Array} source The source metadata.
+ * @returns {Array} Returns `data`.
*/
- function arrayCopy(source, array) {
- var index = -1,
- length = source.length;
+ function mergeData(data, source) {
+ var bitmask = data[1],
+ srcBitmask = source[1],
+ newBitmask = bitmask | srcBitmask,
+ isCommon = newBitmask < ARY_FLAG;
- array || (array = Array(length));
- while (++index < length) {
- array[index] = source[index];
+ var isCombo =
+ (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) ||
+ (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) ||
+ (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);
+
+ // Exit early if metadata can't be merged.
+ if (!(isCommon || isCombo)) {
+ return data;
}
- return array;
+ // Use source `thisArg` if available.
+ if (srcBitmask & BIND_FLAG) {
+ data[2] = source[2];
+ // Set when currying a bound function.
+ newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
+ }
+ // Compose partial arguments.
+ var value = source[3];
+ if (value) {
+ var partials = data[3];
+ data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
+ }
+ // Compose partial right arguments.
+ value = source[5];
+ if (value) {
+ partials = data[5];
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
+ }
+ // Use source `argPos` if available.
+ value = source[7];
+ if (value) {
+ data[7] = arrayCopy(value);
+ }
+ // Use source `ary` if it's smaller.
+ if (srcBitmask & ARY_FLAG) {
+ data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
+ }
+ // Use source `arity` if one is not provided.
+ if (data[9] == null) {
+ data[9] = source[9];
+ }
+ // Use source `func` and merge bitmasks.
+ data[0] = source[0];
+ data[1] = newBitmask;
+
+ return data;
}
/**
- * A specialized version of `_.forEach` for arrays without support for callback
- * shorthands and `this` binding.
+ * A specialized version of `_.pick` which picks `object` properties specified
+ * by `props`.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns `array`.
+ * @param {Object} object The source object.
+ * @param {string[]} props The property names to pick.
+ * @returns {Object} Returns the new object.
*/
- function arrayEach(array, iteratee) {
+ function pickByArray(object, props) {
+ object = toObject(object);
+
var index = -1,
- length = array.length;
+ length = props.length,
+ result = {};
while (++index < length) {
- if (iteratee(array[index], index, array) === false) {
- break;
+ var key = props[index];
+ if (key in object) {
+ result[key] = object[key];
}
}
- return array;
+ return result;
}
/**
- * A specialized version of `_.forEachRight` for arrays without support for
- * callback shorthands and `this` binding.
+ * A specialized version of `_.pick` which picks `object` properties `predicate`
+ * returns truthy for.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns `array`.
+ * @param {Object} object The source object.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Object} Returns the new object.
*/
- function arrayEachRight(array, iteratee) {
- var length = array.length;
-
- while (length--) {
- if (iteratee(array[length], length, array) === false) {
- break;
+ function pickByCallback(object, predicate) {
+ var result = {};
+ baseForIn(object, function(value, key, object) {
+ if (predicate(value, key, object)) {
+ result[key] = value;
}
- }
- return array;
+ });
+ return result;
}
/**
- * A specialized version of `_.every` for arrays without support for callback
- * shorthands and `this` binding.
+ * Reorder `array` according to the specified indexes where the element at
+ * the first index is assigned as the first element, the element at
+ * the second index is assigned as the second element, and so on.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if all elements pass the predicate check,
- * else `false`.
+ * @param {Array} array The array to reorder.
+ * @param {Array} indexes The arranged array indexes.
+ * @returns {Array} Returns `array`.
*/
- function arrayEvery(array, predicate) {
- var index = -1,
- length = array.length;
+ function reorder(array, indexes) {
+ var arrLength = array.length,
+ length = nativeMin(indexes.length, arrLength),
+ oldArray = arrayCopy(array);
- while (++index < length) {
- if (!predicate(array[index], index, array)) {
- return false;
- }
+ while (length--) {
+ var index = indexes[length];
+ array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
}
- return true;
+ return array;
}
/**
- * A specialized version of `_.filter` for arrays without support for callback
- * shorthands and `this` binding.
+ * Sets metadata for `func`.
+ *
+ * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
+ * period of time, it will trip its breaker and transition to an identity function
+ * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)
+ * for more details.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {Array} Returns the new filtered array.
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
*/
- function arrayFilter(array, predicate) {
- var index = -1,
- length = array.length,
- resIndex = -1,
- result = [];
+ var setData = (function() {
+ var count = 0,
+ lastCalled = 0;
- while (++index < length) {
- var value = array[index];
- if (predicate(value, index, array)) {
- result[++resIndex] = value;
+ return function(key, value) {
+ var stamp = now(),
+ remaining = HOT_SPAN - (stamp - lastCalled);
+
+ lastCalled = stamp;
+ if (remaining > 0) {
+ if (++count >= HOT_COUNT) {
+ return key;
+ }
+ } else {
+ count = 0;
}
- }
- return result;
- }
+ return baseSetData(key, value);
+ };
+ }());
/**
- * A specialized version of `_.map` for arrays without support for callback
- * shorthands and `this` binding.
+ * A fallback implementation of `_.isPlainObject` which checks if `value`
+ * is an object created by the `Object` constructor or has a `[[Prototype]]`
+ * of `null`.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the new mapped array.
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
*/
- function arrayMap(array, iteratee) {
- var index = -1,
- length = array.length,
- result = Array(length);
+ function shimIsPlainObject(value) {
+ var Ctor,
+ support = lodash.support;
- while (++index < length) {
- result[index] = iteratee(array[index], index, array);
+ // Exit early for non `Object` objects.
+ if (!(isObjectLike(value) && objToString.call(value) == objectTag) ||
+ (!hasOwnProperty.call(value, 'constructor') &&
+ (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
+ return false;
}
- return result;
+ // IE < 9 iterates inherited properties before own properties. If the first
+ // iterated property is an object's own property then there are no inherited
+ // enumerable properties.
+ var result;
+ // In most environments an object's own properties are iterated before
+ // its inherited properties. If the last iterated property is an object's
+ // own property then there are no inherited enumerable properties.
+ baseForIn(value, function(subValue, key) {
+ result = key;
+ });
+ return result === undefined || hasOwnProperty.call(value, result);
}
/**
- * A specialized version of `_.max` for arrays without support for iteratees.
+ * A fallback implementation of `Object.keys` which creates an array of the
+ * own enumerable property names of `object`.
*
* @private
- * @param {Array} array The array to iterate over.
- * @returns {*} Returns the maximum value.
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
*/
- function arrayMax(array) {
+ function shimKeys(object) {
+ var props = keysIn(object),
+ propsLength = props.length,
+ length = propsLength && object.length,
+ support = lodash.support;
+
+ var allowIndexes = length && isLength(length) &&
+ (isArray(object) || (support.nonEnumArgs && isArguments(object)));
+
var index = -1,
- length = array.length,
- result = NEGATIVE_INFINITY;
+ result = [];
- while (++index < length) {
- var value = array[index];
- if (value > result) {
- result = value;
+ while (++index < propsLength) {
+ var key = props[index];
+ if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
+ result.push(key);
}
}
return result;
}
/**
- * A specialized version of `_.min` for arrays without support for iteratees.
+ * Converts `value` to an array-like object if it is not one.
*
* @private
- * @param {Array} array The array to iterate over.
- * @returns {*} Returns the minimum value.
+ * @param {*} value The value to process.
+ * @returns {Array|Object} Returns the array-like object.
*/
- function arrayMin(array) {
- var index = -1,
- length = array.length,
- result = POSITIVE_INFINITY;
-
- while (++index < length) {
- var value = array[index];
- if (value < result) {
- result = value;
- }
+ function toIterable(value) {
+ if (value == null) {
+ return [];
}
- return result;
+ if (!isArrayLike(value)) {
+ return values(value);
+ }
+ return isObject(value) ? value : Object(value);
}
/**
- * A specialized version of `_.reduce` for arrays without support for callback
- * shorthands and `this` binding.
+ * Converts `value` to an object if it is not one.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {*} [accumulator] The initial value.
- * @param {boolean} [initFromArray] Specify using the first element of `array`
- * as the initial value.
- * @returns {*} Returns the accumulated value.
+ * @param {*} value The value to process.
+ * @returns {Object} Returns the object.
*/
- function arrayReduce(array, iteratee, accumulator, initFromArray) {
- var index = -1,
- length = array.length;
-
- if (initFromArray && length) {
- accumulator = array[++index];
- }
- while (++index < length) {
- accumulator = iteratee(accumulator, array[index], index, array);
- }
- return accumulator;
+ function toObject(value) {
+ return isObject(value) ? value : Object(value);
}
/**
- * A specialized version of `_.reduceRight` for arrays without support for
- * callback shorthands and `this` binding.
+ * Converts `value` to property path array if it is not one.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {*} [accumulator] The initial value.
- * @param {boolean} [initFromArray] Specify using the last element of `array`
- * as the initial value.
- * @returns {*} Returns the accumulated value.
+ * @param {*} value The value to process.
+ * @returns {Array} Returns the property path array.
*/
- function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
- var length = array.length;
- if (initFromArray && length) {
- accumulator = array[--length];
- }
- while (length--) {
- accumulator = iteratee(accumulator, array[length], length, array);
+ function toPath(value) {
+ if (isArray(value)) {
+ return value;
}
- return accumulator;
+ var result = [];
+ baseToString(value).replace(rePropName, function(match, number, quote, string) {
+ result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
+ });
+ return result;
}
/**
- * A specialized version of `_.some` for arrays without support for callback
- * shorthands and `this` binding.
+ * Creates a clone of `wrapper`.
*
* @private
- * @param {Array} array The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if any element passes the predicate check,
- * else `false`.
+ * @param {Object} wrapper The wrapper to clone.
+ * @returns {Object} Returns the cloned wrapper.
*/
- function arraySome(array, predicate) {
- var index = -1,
- length = array.length;
-
- while (++index < length) {
- if (predicate(array[index], index, array)) {
- return true;
- }
- }
- return false;
+ function wrapperClone(wrapper) {
+ return wrapper instanceof LazyWrapper
+ ? wrapper.clone()
+ : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));
}
/**
- * A specialized version of `_.sum` for arrays without support for iteratees.
+ * Creates an array of elements split into groups the length of `size`.
+ * If `collection` can't be split evenly, the final chunk will be the remaining
+ * elements.
*
- * @private
- * @param {Array} array The array to iterate over.
- * @returns {number} Returns the sum.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to process.
+ * @param {number} [size=1] The length of each chunk.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the new array containing chunks.
+ * @example
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 2);
+ * // => [['a', 'b'], ['c', 'd']]
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 3);
+ * // => [['a', 'b', 'c'], ['d']]
*/
- function arraySum(array) {
- var length = array.length,
- result = 0;
+ function chunk(array, size, guard) {
+ if (guard ? isIterateeCall(array, size, guard) : size == null) {
+ size = 1;
+ } else {
+ size = nativeMax(+size || 1, 1);
+ }
+ var index = 0,
+ length = array ? array.length : 0,
+ resIndex = -1,
+ result = Array(ceil(length / size));
- while (length--) {
- result += +array[length] || 0;
+ while (index < length) {
+ result[++resIndex] = baseSlice(array, index, (index += size));
}
return result;
}
/**
- * Used by `_.defaults` to customize its `_.assign` use.
- *
- * @private
- * @param {*} objectValue The destination object property value.
- * @param {*} sourceValue The source object property value.
- * @returns {*} Returns the value to assign to the destination object.
- */
- function assignDefaults(objectValue, sourceValue) {
- return objectValue === undefined ? sourceValue : objectValue;
- }
-
- /**
- * Used by `_.template` to customize its `_.assign` use.
- *
- * **Note:** This function is like `assignDefaults` except that it ignores
- * inherited property values when checking if a property is `undefined`.
+ * Creates an array with all falsey values removed. The values `false`, `null`,
+ * `0`, `""`, `undefined`, and `NaN` are falsey.
*
- * @private
- * @param {*} objectValue The destination object property value.
- * @param {*} sourceValue The source object property value.
- * @param {string} key The key associated with the object and source values.
- * @param {Object} object The destination object.
- * @returns {*} Returns the value to assign to the destination object.
- */
- function assignOwnDefaults(objectValue, sourceValue, key, object) {
- return (objectValue === undefined || !hasOwnProperty.call(object, key))
- ? sourceValue
- : objectValue;
- }
-
- /**
- * A specialized version of `_.assign` for customizing assigned values without
- * support for argument juggling, multiple sources, and `this` binding `customizer`
- * functions.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to compact.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
*
- * @private
- * @param {Object} object The destination object.
- * @param {Object} source The source object.
- * @param {Function} customizer The function to customize assigned values.
- * @returns {Object} Returns `object`.
+ * _.compact([0, 1, false, 2, '', 3]);
+ * // => [1, 2, 3]
*/
- function assignWith(object, source, customizer) {
- var props = keys(source);
- push.apply(props, getSymbols(source));
-
+ function compact(array) {
var index = -1,
- length = props.length;
+ length = array ? array.length : 0,
+ resIndex = -1,
+ result = [];
while (++index < length) {
- var key = props[index],
- value = object[key],
- result = customizer(value, source[key], key, object, source);
-
- if ((result === result ? (result !== value) : (value === value)) ||
- (value === undefined && !(key in object))) {
- object[key] = result;
+ var value = array[index];
+ if (value) {
+ result[++resIndex] = value;
}
}
- return object;
+ return result;
}
/**
- * The base implementation of `_.assign` without support for argument juggling,
- * multiple sources, and `customizer` functions.
+ * Creates an array excluding all values of the provided arrays using
+ * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+ * for equality comparisons.
*
- * @private
- * @param {Object} object The destination object.
- * @param {Object} source The source object.
- * @returns {Object} Returns `object`.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The arrays of values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.difference([1, 2, 3], [4, 2]);
+ * // => [1, 3]
*/
- var baseAssign = nativeAssign || function(object, source) {
- return source == null
- ? object
- : baseCopy(source, getSymbols(source), baseCopy(source, keys(source), object));
- };
+ var difference = restParam(function(array, values) {
+ return isArrayLike(array)
+ ? baseDifference(array, baseFlatten(values, false, true))
+ : [];
+ });
/**
- * The base implementation of `_.at` without support for string collections
- * and individual key arguments.
+ * Creates a slice of `array` with `n` elements dropped from the beginning.
*
- * @private
- * @param {Array|Object} collection The collection to iterate over.
- * @param {number[]|string[]} props The property names or indexes of elements to pick.
- * @returns {Array} Returns the new array of picked elements.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.drop([1, 2, 3]);
+ * // => [2, 3]
+ *
+ * _.drop([1, 2, 3], 2);
+ * // => [3]
+ *
+ * _.drop([1, 2, 3], 5);
+ * // => []
+ *
+ * _.drop([1, 2, 3], 0);
+ * // => [1, 2, 3]
*/
- function baseAt(collection, props) {
- var index = -1,
- length = collection.length,
- isArr = isLength(length),
- propsLength = props.length,
- result = Array(propsLength);
-
- while(++index < propsLength) {
- var key = props[index];
- if (isArr) {
- result[index] = isIndex(key, length) ? collection[key] : undefined;
- } else {
- result[index] = collection[key];
- }
+ function drop(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
}
- return result;
+ if (guard ? isIterateeCall(array, n, guard) : n == null) {
+ n = 1;
+ }
+ return baseSlice(array, n < 0 ? 0 : n);
}
/**
- * Copies properties of `source` to `object`.
+ * Creates a slice of `array` with `n` elements dropped from the end.
*
- * @private
- * @param {Object} source The object to copy properties from.
- * @param {Array} props The property names to copy.
- * @param {Object} [object={}] The object to copy properties to.
- * @returns {Object} Returns `object`.
- */
- function baseCopy(source, props, object) {
- object || (object = {});
-
- var index = -1,
- length = props.length;
-
- while (++index < length) {
- var key = props[index];
- object[key] = source[key];
- }
- return object;
- }
-
- /**
- * The base implementation of `_.callback` which supports specifying the
- * number of arguments to provide to `func`.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
*
- * @private
- * @param {*} [func=_.identity] The value to convert to a callback.
- * @param {*} [thisArg] The `this` binding of `func`.
- * @param {number} [argCount] The number of arguments to provide to `func`.
- * @returns {Function} Returns the callback.
+ * _.dropRight([1, 2, 3]);
+ * // => [1, 2]
+ *
+ * _.dropRight([1, 2, 3], 2);
+ * // => [1]
+ *
+ * _.dropRight([1, 2, 3], 5);
+ * // => []
+ *
+ * _.dropRight([1, 2, 3], 0);
+ * // => [1, 2, 3]
*/
- function baseCallback(func, thisArg, argCount) {
- var type = typeof func;
- if (type == 'function') {
- return thisArg === undefined
- ? func
- : bindCallback(func, thisArg, argCount);
- }
- if (func == null) {
- return identity;
+ function dropRight(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
}
- if (type == 'object') {
- return baseMatches(func);
+ if (guard ? isIterateeCall(array, n, guard) : n == null) {
+ n = 1;
}
- return thisArg === undefined
- ? property(func)
- : baseMatchesProperty(func, thisArg);
+ n = length - (+n || 0);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
}
/**
- * The base implementation of `_.clone` without support for argument juggling
- * and `this` binding `customizer` functions.
+ * Creates a slice of `array` excluding elements dropped from the end.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * bound to `thisArg` and invoked with three arguments: (value, index, array).
*
- * @private
- * @param {*} value The value to clone.
- * @param {boolean} [isDeep] Specify a deep clone.
- * @param {Function} [customizer] The function to customize cloning values.
- * @param {string} [key] The key of `value`.
- * @param {Object} [object] The object `value` belongs to.
- * @param {Array} [stackA=[]] Tracks traversed source objects.
- * @param {Array} [stackB=[]] Associates clones with source counterparts.
- * @returns {*} Returns the cloned value.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that match the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.dropRightWhile([1, 2, 3], function(n) {
+ * return n > 1;
+ * });
+ * // => [1]
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.dropRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
+ * // => ['barney', 'fred']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.dropRightWhile(users, 'active', false), 'user');
+ * // => ['barney']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.dropRightWhile(users, 'active'), 'user');
+ * // => ['barney', 'fred', 'pebbles']
*/
- function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
- var result;
- if (customizer) {
- result = object ? customizer(value, key, object) : customizer(value);
- }
- if (result !== undefined) {
- return result;
- }
- if (!isObject(value)) {
- return value;
- }
- var isArr = isArray(value);
- if (isArr) {
- result = initCloneArray(value);
- if (!isDeep) {
- return arrayCopy(value, result);
- }
- } else {
- var tag = objToString.call(value),
- isFunc = tag == funcTag;
-
- if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
- result = initCloneObject(isFunc ? {} : value);
- if (!isDeep) {
- return baseAssign(result, value);
- }
- } else {
- return cloneableTags[tag]
- ? initCloneByTag(value, tag, isDeep)
- : (object ? value : {});
- }
- }
- // Check for circular references and return corresponding clone.
- stackA || (stackA = []);
- stackB || (stackB = []);
-
- var length = stackA.length;
- while (length--) {
- if (stackA[length] == value) {
- return stackB[length];
- }
- }
- // Add the source value to the stack of traversed objects and associate it with its clone.
- stackA.push(value);
- stackB.push(result);
-
- // Recursively populate clone (susceptible to call stack limits).
- (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
- result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
- });
- return result;
+ function dropRightWhile(array, predicate, thisArg) {
+ return (array && array.length)
+ ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true)
+ : [];
}
/**
- * The base implementation of `_.create` without support for assigning
- * properties to the created object.
+ * Creates a slice of `array` excluding elements dropped from the beginning.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * bound to `thisArg` and invoked with three arguments: (value, index, array).
*
- * @private
- * @param {Object} prototype The object to inherit from.
- * @returns {Object} Returns the new object.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.dropWhile([1, 2, 3], function(n) {
+ * return n < 3;
+ * });
+ * // => [3]
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.dropWhile(users, { 'user': 'barney', 'active': false }), 'user');
+ * // => ['fred', 'pebbles']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.dropWhile(users, 'active', false), 'user');
+ * // => ['pebbles']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.dropWhile(users, 'active'), 'user');
+ * // => ['barney', 'fred', 'pebbles']
*/
- var baseCreate = (function() {
- function Object() {}
- return function(prototype) {
- if (isObject(prototype)) {
- Object.prototype = prototype;
- var result = new Object;
- Object.prototype = null;
- }
- return result || context.Object();
- };
- }());
+ function dropWhile(array, predicate, thisArg) {
+ return (array && array.length)
+ ? baseWhile(array, getCallback(predicate, thisArg, 3), true)
+ : [];
+ }
/**
- * The base implementation of `_.delay` and `_.defer` which accepts an index
- * of where to slice the arguments to provide to `func`.
+ * Fills elements of `array` with `value` from `start` up to, but not
+ * including, `end`.
*
- * @private
- * @param {Function} func The function to delay.
- * @param {number} wait The number of milliseconds to delay invocation.
- * @param {Object} args The arguments provide to `func`.
- * @returns {number} Returns the timer id.
- */
- function baseDelay(func, wait, args) {
- if (typeof func != 'function') {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- return setTimeout(function() { func.apply(undefined, args); }, wait);
- }
-
- /**
- * The base implementation of `_.difference` which accepts a single array
- * of values to exclude.
+ * **Note:** This method mutates `array`.
*
- * @private
- * @param {Array} array The array to inspect.
- * @param {Array} values The values to exclude.
- * @returns {Array} Returns the new array of filtered values.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _.fill(array, 'a');
+ * console.log(array);
+ * // => ['a', 'a', 'a']
+ *
+ * _.fill(Array(3), 2);
+ * // => [2, 2, 2]
+ *
+ * _.fill([4, 6, 8], '*', 1, 2);
+ * // => [4, '*', 8]
*/
- function baseDifference(array, values) {
- var length = array ? array.length : 0,
- result = [];
-
+ function fill(array, value, start, end) {
+ var length = array ? array.length : 0;
if (!length) {
- return result;
- }
- var index = -1,
- indexOf = getIndexOf(),
- isCommon = indexOf == baseIndexOf,
- cache = (isCommon && values.length >= 200) ? createCache(values) : null,
- valuesLength = values.length;
-
- if (cache) {
- indexOf = cacheIndexOf;
- isCommon = false;
- values = cache;
+ return [];
}
- outer:
- while (++index < length) {
- var value = array[index];
-
- if (isCommon && value === value) {
- var valuesIndex = valuesLength;
- while (valuesIndex--) {
- if (values[valuesIndex] === value) {
- continue outer;
- }
- }
- result.push(value);
- }
- else if (indexOf(values, value, 0) < 0) {
- result.push(value);
- }
+ if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
+ start = 0;
+ end = length;
}
- return result;
+ return baseFill(array, value, start, end);
}
/**
- * The base implementation of `_.forEach` without support for callback
- * shorthands and `this` binding.
+ * This method is like `_.find` except that it returns the index of the first
+ * element `predicate` returns truthy for instead of the element itself.
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array|Object|string} Returns `collection`.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.findIndex(users, function(chr) {
+ * return chr.user == 'barney';
+ * });
+ * // => 0
+ *
+ * // using the `_.matches` callback shorthand
+ * _.findIndex(users, { 'user': 'fred', 'active': false });
+ * // => 1
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.findIndex(users, 'active', false);
+ * // => 0
+ *
+ * // using the `_.property` callback shorthand
+ * _.findIndex(users, 'active');
+ * // => 2
*/
- var baseEach = createBaseEach(baseForOwn);
+ var findIndex = createFindIndex();
/**
- * The base implementation of `_.forEachRight` without support for callback
- * shorthands and `this` binding.
+ * This method is like `_.findIndex` except that it iterates over elements
+ * of `collection` from right to left.
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array|Object|string} Returns `collection`.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.findLastIndex(users, function(chr) {
+ * return chr.user == 'pebbles';
+ * });
+ * // => 2
+ *
+ * // using the `_.matches` callback shorthand
+ * _.findLastIndex(users, { 'user': 'barney', 'active': true });
+ * // => 0
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.findLastIndex(users, 'active', false);
+ * // => 2
+ *
+ * // using the `_.property` callback shorthand
+ * _.findLastIndex(users, 'active');
+ * // => 0
*/
- var baseEachRight = createBaseEach(baseForOwnRight, true);
+ var findLastIndex = createFindIndex(true);
/**
- * The base implementation of `_.every` without support for callback
- * shorthands and `this` binding.
+ * Gets the first element of `array`.
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if all elements pass the predicate check,
- * else `false`
+ * @static
+ * @memberOf _
+ * @alias head
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the first element of `array`.
+ * @example
+ *
+ * _.first([1, 2, 3]);
+ * // => 1
+ *
+ * _.first([]);
+ * // => undefined
*/
- function baseEvery(collection, predicate) {
- var result = true;
- baseEach(collection, function(value, index, collection) {
- result = !!predicate(value, index, collection);
- return result;
- });
- return result;
+ function first(array) {
+ return array ? array[0] : undefined;
}
/**
- * The base implementation of `_.fill` without an iteratee call guard.
+ * Flattens a nested array. If `isDeep` is `true` the array is recursively
+ * flattened, otherwise it is only flattened a single level.
*
- * @private
- * @param {Array} array The array to fill.
- * @param {*} value The value to fill `array` with.
- * @param {number} [start=0] The start position.
- * @param {number} [end=array.length] The end position.
- * @returns {Array} Returns `array`.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @param {boolean} [isDeep] Specify a deep flatten.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flatten([1, [2, 3, [4]]]);
+ * // => [1, 2, 3, [4]]
+ *
+ * // using `isDeep`
+ * _.flatten([1, [2, 3, [4]]], true);
+ * // => [1, 2, 3, 4]
*/
- function baseFill(array, value, start, end) {
- var length = array.length;
-
- start = start == null ? 0 : (+start || 0);
- if (start < 0) {
- start = -start > length ? 0 : (length + start);
- }
- end = (end === undefined || end > length) ? length : (+end || 0);
- if (end < 0) {
- end += length;
+ function flatten(array, isDeep, guard) {
+ var length = array ? array.length : 0;
+ if (guard && isIterateeCall(array, isDeep, guard)) {
+ isDeep = false;
}
- length = start > end ? 0 : (end >>> 0);
- start >>>= 0;
+ return length ? baseFlatten(array, isDeep) : [];
+ }
- while (start < length) {
- array[start++] = value;
- }
- return array;
+ /**
+ * Recursively flattens a nested array.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to recursively flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flattenDeep([1, [2, 3, [4]]]);
+ * // => [1, 2, 3, 4]
+ */
+ function flattenDeep(array) {
+ var length = array ? array.length : 0;
+ return length ? baseFlatten(array, true) : [];
}
/**
- * The base implementation of `_.filter` without support for callback
- * shorthands and `this` binding.
+ * Gets the index at which the first occurrence of `value` is found in `array`
+ * using [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+ * for equality comparisons. If `fromIndex` is negative, it is used as the offset
+ * from the end of `array`. If `array` is sorted providing `true` for `fromIndex`
+ * performs a faster binary search.
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {Array} Returns the new filtered array.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {boolean|number} [fromIndex=0] The index to search from or `true`
+ * to perform a binary search on a sorted array.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.indexOf([1, 2, 1, 2], 2);
+ * // => 1
+ *
+ * // using `fromIndex`
+ * _.indexOf([1, 2, 1, 2], 2, 2);
+ * // => 3
+ *
+ * // performing a binary search
+ * _.indexOf([1, 1, 2, 2], 2, true);
+ * // => 2
*/
- function baseFilter(collection, predicate) {
- var result = [];
- baseEach(collection, function(value, index, collection) {
- if (predicate(value, index, collection)) {
- result.push(value);
+ function indexOf(array, value, fromIndex) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return -1;
+ }
+ if (typeof fromIndex == 'number') {
+ fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
+ } else if (fromIndex) {
+ var index = binaryIndex(array, value),
+ other = array[index];
+
+ if (value === value ? (value === other) : (other !== other)) {
+ return index;
}
- });
- return result;
+ return -1;
+ }
+ return baseIndexOf(array, value, fromIndex || 0);
}
/**
- * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,
- * without support for callback shorthands and `this` binding, which iterates
- * over `collection` using the provided `eachFunc`.
+ * Gets all but the last element of `array`.
*
- * @private
- * @param {Array|Object|string} collection The collection to search.
- * @param {Function} predicate The function invoked per iteration.
- * @param {Function} eachFunc The function to iterate over `collection`.
- * @param {boolean} [retKey] Specify returning the key of the found element
- * instead of the element itself.
- * @returns {*} Returns the found element or its key, else `undefined`.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.initial([1, 2, 3]);
+ * // => [1, 2]
*/
- function baseFind(collection, predicate, eachFunc, retKey) {
- var result;
- eachFunc(collection, function(value, key, collection) {
- if (predicate(value, key, collection)) {
- result = retKey ? key : value;
- return false;
- }
- });
- return result;
+ function initial(array) {
+ return dropRight(array, 1);
}
/**
- * The base implementation of `_.flatten` with added support for restricting
- * flattening and specifying the start index.
+ * Creates an array of unique values in all provided arrays using
+ * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+ * for equality comparisons.
*
- * @private
- * @param {Array} array The array to flatten.
- * @param {boolean} isDeep Specify a deep flatten.
- * @param {boolean} isStrict Restrict flattening to arrays and `arguments` objects.
- * @returns {Array} Returns the new flattened array.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of shared values.
+ * @example
+ * _.intersection([1, 2], [4, 2], [2, 1]);
+ * // => [2]
*/
- function baseFlatten(array, isDeep, isStrict) {
- var index = -1,
- length = array.length,
- resIndex = -1,
+ function intersection() {
+ var args = [],
+ argsIndex = -1,
+ argsLength = arguments.length,
+ caches = [],
+ indexOf = getIndexOf(),
+ isCommon = indexOf == baseIndexOf,
result = [];
- while (++index < length) {
- var value = array[index];
+ while (++argsIndex < argsLength) {
+ var value = arguments[argsIndex];
+ if (isArrayLike(value)) {
+ args.push(value);
+ caches.push((isCommon && value.length >= 120) ? createCache(argsIndex && value) : null);
+ }
+ }
+ argsLength = args.length;
+ if (argsLength < 2) {
+ return result;
+ }
+ var array = args[0],
+ index = -1,
+ length = array ? array.length : 0,
+ seen = caches[0];
- if (isObjectLike(value) && isLength(value.length) && (isArray(value) || isArguments(value))) {
- if (isDeep) {
- // Recursively flatten arrays (susceptible to call stack limits).
- value = baseFlatten(value, isDeep, isStrict);
+ outer:
+ while (++index < length) {
+ value = array[index];
+ if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) {
+ argsIndex = argsLength;
+ while (--argsIndex) {
+ var cache = caches[argsIndex];
+ if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value, 0)) < 0) {
+ continue outer;
+ }
}
- var valIndex = -1,
- valLength = value.length;
-
- result.length += valLength;
- while (++valIndex < valLength) {
- result[++resIndex] = value[valIndex];
+ if (seen) {
+ seen.push(value);
}
- } else if (!isStrict) {
- result[++resIndex] = value;
+ result.push(value);
}
}
return result;
}
/**
- * The base implementation of `baseForIn` and `baseForOwn` which iterates
- * over `object` properties returned by `keysFunc` invoking `iteratee` for
- * each property. Iteratee functions may exit iteration early by explicitly
- * returning `false`.
+ * Gets the last element of `array`.
*
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {Function} keysFunc The function to get the keys of `object`.
- * @returns {Object} Returns `object`.
- */
- var baseFor = createBaseFor();
-
- /**
- * This function is like `baseFor` except that it iterates over properties
- * in the opposite order.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the last element of `array`.
+ * @example
*
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {Function} keysFunc The function to get the keys of `object`.
- * @returns {Object} Returns `object`.
+ * _.last([1, 2, 3]);
+ * // => 3
*/
- var baseForRight = createBaseFor(true);
+ function last(array) {
+ var length = array ? array.length : 0;
+ return length ? array[length - 1] : undefined;
+ }
/**
- * The base implementation of `_.forIn` without support for callback
- * shorthands and `this` binding.
+ * This method is like `_.indexOf` except that it iterates over elements of
+ * `array` from right to left.
*
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Object} Returns `object`.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {boolean|number} [fromIndex=array.length-1] The index to search from
+ * or `true` to perform a binary search on a sorted array.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.lastIndexOf([1, 2, 1, 2], 2);
+ * // => 3
+ *
+ * // using `fromIndex`
+ * _.lastIndexOf([1, 2, 1, 2], 2, 2);
+ * // => 1
+ *
+ * // performing a binary search
+ * _.lastIndexOf([1, 1, 2, 2], 2, true);
+ * // => 3
*/
- function baseForIn(object, iteratee) {
- return baseFor(object, iteratee, keysIn);
+ function lastIndexOf(array, value, fromIndex) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return -1;
+ }
+ var index = length;
+ if (typeof fromIndex == 'number') {
+ index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1;
+ } else if (fromIndex) {
+ index = binaryIndex(array, value, true) - 1;
+ var other = array[index];
+ if (value === value ? (value === other) : (other !== other)) {
+ return index;
+ }
+ return -1;
+ }
+ if (value !== value) {
+ return indexOfNaN(array, index, true);
+ }
+ while (index--) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
}
/**
- * The base implementation of `_.forOwn` without support for callback
- * shorthands and `this` binding.
+ * Removes all provided values from `array` using
+ * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+ * for equality comparisons.
*
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Object} Returns `object`.
+ * **Note:** Unlike `_.without`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...*} [values] The values to remove.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3, 1, 2, 3];
+ *
+ * _.pull(array, 2, 3);
+ * console.log(array);
+ * // => [1, 1]
*/
- function baseForOwn(object, iteratee) {
- return baseFor(object, iteratee, keys);
+ function pull() {
+ var args = arguments,
+ array = args[0];
+
+ if (!(array && array.length)) {
+ return array;
+ }
+ var index = 0,
+ indexOf = getIndexOf(),
+ length = args.length;
+
+ while (++index < length) {
+ var fromIndex = 0,
+ value = args[index];
+
+ while ((fromIndex = indexOf(array, value, fromIndex)) > -1) {
+ splice.call(array, fromIndex, 1);
+ }
+ }
+ return array;
}
/**
- * The base implementation of `_.forOwnRight` without support for callback
- * shorthands and `this` binding.
+ * Removes elements from `array` corresponding to the given indexes and returns
+ * an array of the removed elements. Indexes may be specified as an array of
+ * indexes or as individual arguments.
*
- * @private
- * @param {Object} object The object to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Object} Returns `object`.
+ * **Note:** Unlike `_.at`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...(number|number[])} [indexes] The indexes of elements to remove,
+ * specified as individual indexes or arrays of indexes.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = [5, 10, 15, 20];
+ * var evens = _.pullAt(array, 1, 3);
+ *
+ * console.log(array);
+ * // => [5, 15]
+ *
+ * console.log(evens);
+ * // => [10, 20]
*/
- function baseForOwnRight(object, iteratee) {
- return baseForRight(object, iteratee, keys);
- }
+ var pullAt = restParam(function(array, indexes) {
+ indexes = baseFlatten(indexes);
+
+ var result = baseAt(array, indexes);
+ basePullAt(array, indexes.sort(baseCompareAscending));
+ return result;
+ });
/**
- * The base implementation of `_.functions` which creates an array of
- * `object` function property names filtered from those provided.
+ * Removes all elements from `array` that `predicate` returns truthy for
+ * and returns an array of the removed elements. The predicate is bound to
+ * `thisArg` and invoked with three arguments: (value, index, array).
*
- * @private
- * @param {Object} object The object to inspect.
- * @param {Array} props The property names to filter.
- * @returns {Array} Returns the new array of filtered property names.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * **Note:** Unlike `_.filter`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = [1, 2, 3, 4];
+ * var evens = _.remove(array, function(n) {
+ * return n % 2 == 0;
+ * });
+ *
+ * console.log(array);
+ * // => [1, 3]
+ *
+ * console.log(evens);
+ * // => [2, 4]
*/
- function baseFunctions(object, props) {
+ function remove(array, predicate, thisArg) {
+ var result = [];
+ if (!(array && array.length)) {
+ return result;
+ }
var index = -1,
- length = props.length,
- resIndex = -1,
- result = [];
+ indexes = [],
+ length = array.length;
+ predicate = getCallback(predicate, thisArg, 3);
while (++index < length) {
- var key = props[index];
- if (isFunction(object[key])) {
- result[++resIndex] = key;
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result.push(value);
+ indexes.push(index);
}
}
+ basePullAt(array, indexes);
return result;
}
/**
- * The base implementation of `get` without support for string paths
- * and default values.
+ * Gets all but the first element of `array`.
*
- * @private
- * @param {Object} object The object to query.
- * @param {Array} path The path of the property to get.
- * @param {string} [pathKey] The key representation of path.
- * @returns {*} Returns the resolved value.
+ * @static
+ * @memberOf _
+ * @alias tail
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.rest([1, 2, 3]);
+ * // => [2, 3]
*/
- function baseGet(object, path, pathKey) {
- if (object == null) {
- return;
- }
- if (pathKey !== undefined && pathKey in toObject(object)) {
- path = [pathKey];
- }
- var index = -1,
- length = path.length;
-
- while (object != null && ++index < length) {
- var result = object = object[path[index]];
- }
- return result;
+ function rest(array) {
+ return drop(array, 1);
}
/**
- * The base implementation of `_.isEqual` without support for `this` binding
- * `customizer` functions.
+ * Creates a slice of `array` from `start` up to, but not including, `end`.
*
- * @private
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @param {Function} [customizer] The function to customize comparing values.
- * @param {boolean} [isLoose] Specify performing partial comparisons.
- * @param {Array} [stackA] Tracks traversed `value` objects.
- * @param {Array} [stackB] Tracks traversed `other` objects.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * **Note:** This method is used instead of `Array#slice` to support node
+ * lists in IE < 9 and to ensure dense arrays are returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
*/
- function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
- // Exit early for identical values.
- if (value === other) {
- // Treat `+0` vs. `-0` as not equal.
- return value !== 0 || (1 / value == 1 / other);
+ function slice(array, start, end) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
}
- var valType = typeof value,
- othType = typeof other;
-
- // Exit early for unlike primitive values.
- if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') ||
- value == null || other == null) {
- // Return `false` unless both values are `NaN`.
- return value !== value && other !== other;
+ if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
+ start = 0;
+ end = length;
}
- return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
+ return baseSlice(array, start, end);
}
/**
- * A specialized version of `baseIsEqual` for arrays and objects which performs
- * deep comparisons and tracks traversed objects enabling objects with circular
- * references to be compared.
+ * Uses a binary search to determine the lowest index at which `value` should
+ * be inserted into `array` in order to maintain its sort order. If an iteratee
+ * function is provided it is invoked for `value` and each element of `array`
+ * to compute their sort ranking. The iteratee is bound to `thisArg` and
+ * invoked with one argument; (value).
*
- * @private
- * @param {Object} object The object to compare.
- * @param {Object} other The other object to compare.
- * @param {Function} equalFunc The function to determine equivalents of values.
- * @param {Function} [customizer] The function to customize comparing objects.
- * @param {boolean} [isLoose] Specify performing partial comparisons.
- * @param {Array} [stackA=[]] Tracks traversed `value` objects.
- * @param {Array} [stackB=[]] Tracks traversed `other` objects.
- * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
- */
- function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
- var objIsArr = isArray(object),
- othIsArr = isArray(other),
- objTag = arrayTag,
- othTag = arrayTag;
-
- if (!objIsArr) {
- objTag = objToString.call(object);
- if (objTag == argsTag) {
- objTag = objectTag;
- } else if (objTag != objectTag) {
- objIsArr = isTypedArray(object);
- }
- }
- if (!othIsArr) {
- othTag = objToString.call(other);
- if (othTag == argsTag) {
- othTag = objectTag;
- } else if (othTag != objectTag) {
- othIsArr = isTypedArray(other);
- }
- }
- var objIsObj = objTag == objectTag,
- othIsObj = othTag == objectTag,
- isSameTag = objTag == othTag;
-
- if (isSameTag && !(objIsArr || objIsObj)) {
- return equalByTag(object, other, objTag);
- }
- if (!isLoose) {
- var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
- othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
-
- if (valWrapped || othWrapped) {
- return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
- }
- }
- if (!isSameTag) {
- return false;
- }
- // Assume cyclic values are equal.
- // For more information on detecting circular references see https://es5.github.io/#JO.
- stackA || (stackA = []);
- stackB || (stackB = []);
-
- var length = stackA.length;
- while (length--) {
- if (stackA[length] == object) {
- return stackB[length] == other;
- }
- }
- // Add `object` and `other` to the stack of traversed objects.
- stackA.push(object);
- stackB.push(other);
-
- var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);
-
- stackA.pop();
- stackB.pop();
-
- return result;
- }
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedIndex([30, 50], 40);
+ * // => 1
+ *
+ * _.sortedIndex([4, 4, 5, 5], 5);
+ * // => 2
+ *
+ * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } };
+ *
+ * // using an iteratee function
+ * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) {
+ * return this.data[word];
+ * }, dict);
+ * // => 1
+ *
+ * // using the `_.property` callback shorthand
+ * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+ * // => 1
+ */
+ var sortedIndex = createSortedIndex();
/**
- * The base implementation of `_.isMatch` without support for callback
- * shorthands and `this` binding.
+ * This method is like `_.sortedIndex` except that it returns the highest
+ * index at which `value` should be inserted into `array` in order to
+ * maintain its sort order.
*
- * @private
- * @param {Object} object The object to inspect.
- * @param {Array} props The source property names to match.
- * @param {Array} values The source values to match.
- * @param {Array} strictCompareFlags Strict comparison flags for source values.
- * @param {Function} [customizer] The function to customize comparing objects.
- * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedLastIndex([4, 4, 5, 5], 5);
+ * // => 4
*/
- function baseIsMatch(object, props, values, strictCompareFlags, customizer) {
- var index = -1,
- length = props.length,
- noCustomizer = !customizer;
-
- while (++index < length) {
- if ((noCustomizer && strictCompareFlags[index])
- ? values[index] !== object[props[index]]
- : !(props[index] in object)
- ) {
- return false;
- }
- }
- index = -1;
- while (++index < length) {
- var key = props[index],
- objValue = object[key],
- srcValue = values[index];
-
- if (noCustomizer && strictCompareFlags[index]) {
- var result = objValue !== undefined || (key in object);
- } else {
- result = customizer ? customizer(objValue, srcValue, key) : undefined;
- if (result === undefined) {
- result = baseIsEqual(srcValue, objValue, customizer, true);
- }
- }
- if (!result) {
- return false;
- }
- }
- return true;
- }
+ var sortedLastIndex = createSortedIndex(true);
/**
- * The base implementation of `_.map` without support for callback shorthands
- * and `this` binding.
+ * Creates a slice of `array` with `n` elements taken from the beginning.
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the new mapped array.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.take([1, 2, 3]);
+ * // => [1]
+ *
+ * _.take([1, 2, 3], 2);
+ * // => [1, 2]
+ *
+ * _.take([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.take([1, 2, 3], 0);
+ * // => []
*/
- function baseMap(collection, iteratee) {
- var index = -1,
- length = getLength(collection),
- result = isLength(length) ? Array(length) : [];
-
- baseEach(collection, function(value, key, collection) {
- result[++index] = iteratee(value, key, collection);
- });
- return result;
+ function take(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (guard ? isIterateeCall(array, n, guard) : n == null) {
+ n = 1;
+ }
+ return baseSlice(array, 0, n < 0 ? 0 : n);
}
/**
- * The base implementation of `_.matches` which does not clone `source`.
+ * Creates a slice of `array` with `n` elements taken from the end.
*
- * @private
- * @param {Object} source The object of property values to match.
- * @returns {Function} Returns the new function.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeRight([1, 2, 3]);
+ * // => [3]
+ *
+ * _.takeRight([1, 2, 3], 2);
+ * // => [2, 3]
+ *
+ * _.takeRight([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.takeRight([1, 2, 3], 0);
+ * // => []
*/
- function baseMatches(source) {
- var props = keys(source),
- length = props.length;
-
+ function takeRight(array, n, guard) {
+ var length = array ? array.length : 0;
if (!length) {
- return constant(true);
- }
- if (length == 1) {
- var key = props[0],
- value = source[key];
-
- if (isStrictComparable(value)) {
- return function(object) {
- if (object == null) {
- return false;
- }
- return object[key] === value && (value !== undefined || (key in toObject(object)));
- };
- }
+ return [];
}
- var values = Array(length),
- strictCompareFlags = Array(length);
-
- while (length--) {
- value = source[props[length]];
- values[length] = value;
- strictCompareFlags[length] = isStrictComparable(value);
+ if (guard ? isIterateeCall(array, n, guard) : n == null) {
+ n = 1;
}
- return function(object) {
- return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags);
- };
+ n = length - (+n || 0);
+ return baseSlice(array, n < 0 ? 0 : n);
}
/**
- * The base implementation of `_.matchesProperty` which does not which does
- * not clone `value`.
+ * Creates a slice of `array` with elements taken from the end. Elements are
+ * taken until `predicate` returns falsey. The predicate is bound to `thisArg`
+ * and invoked with three arguments: (value, index, array).
*
- * @private
- * @param {string} path The path of the property to get.
- * @param {*} value The value to compare.
- * @returns {Function} Returns the new function.
- */
- function baseMatchesProperty(path, value) {
- var isArr = isArray(path),
- isCommon = isKey(path) && isStrictComparable(value),
- pathKey = (path + '');
-
- path = toPath(path);
- return function(object) {
- if (object == null) {
- return false;
- }
- var key = pathKey;
- object = toObject(object);
- if ((isArr || !isCommon) && !(key in object)) {
- object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
- if (object == null) {
- return false;
- }
- key = last(path);
- object = toObject(object);
- }
- return object[key] === value
- ? (value !== undefined || (key in object))
- : baseIsEqual(value, object[key], null, true);
- };
- }
-
- /**
- * The base implementation of `_.merge` without support for argument juggling,
- * multiple sources, and `this` binding `customizer` functions.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
*
- * @private
- * @param {Object} object The destination object.
- * @param {Object} source The source object.
- * @param {Function} [customizer] The function to customize merging properties.
- * @param {Array} [stackA=[]] Tracks traversed source objects.
- * @param {Array} [stackB=[]] Associates values with source counterparts.
- * @returns {Object} Returns `object`.
- */
- function baseMerge(object, source, customizer, stackA, stackB) {
- if (!isObject(object)) {
- return object;
- }
- var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source));
- if (!isSrcArr) {
- var props = keys(source);
- push.apply(props, getSymbols(source));
- }
- arrayEach(props || source, function(srcValue, key) {
- if (props) {
- key = srcValue;
- srcValue = source[key];
- }
- if (isObjectLike(srcValue)) {
- stackA || (stackA = []);
- stackB || (stackB = []);
- baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
- }
- else {
- var value = object[key],
- result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
- isCommon = result === undefined;
-
- if (isCommon) {
- result = srcValue;
- }
- if ((isSrcArr || result !== undefined) &&
- (isCommon || (result === result ? (result !== value) : (value === value)))) {
- object[key] = result;
- }
- }
- });
- return object;
- }
-
- /**
- * A specialized version of `baseMerge` for arrays and objects which performs
- * deep merges and tracks traversed objects enabling objects with circular
- * references to be merged.
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
*
- * @private
- * @param {Object} object The destination object.
- * @param {Object} source The source object.
- * @param {string} key The key of the value to merge.
- * @param {Function} mergeFunc The function to merge values.
- * @param {Function} [customizer] The function to customize merging properties.
- * @param {Array} [stackA=[]] Tracks traversed source objects.
- * @param {Array} [stackB=[]] Associates values with source counterparts.
- * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeRightWhile([1, 2, 3], function(n) {
+ * return n > 1;
+ * });
+ * // => [2, 3]
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.takeRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
+ * // => ['pebbles']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.takeRightWhile(users, 'active', false), 'user');
+ * // => ['fred', 'pebbles']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.takeRightWhile(users, 'active'), 'user');
+ * // => []
*/
- function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
- var length = stackA.length,
- srcValue = source[key];
-
- while (length--) {
- if (stackA[length] == srcValue) {
- object[key] = stackB[length];
- return;
- }
- }
- var value = object[key],
- result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
- isCommon = result === undefined;
-
- if (isCommon) {
- result = srcValue;
- if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) {
- result = isArray(value)
- ? value
- : (getLength(value) ? arrayCopy(value) : []);
- }
- else if (isPlainObject(srcValue) || isArguments(srcValue)) {
- result = isArguments(value)
- ? toPlainObject(value)
- : (isPlainObject(value) ? value : {});
- }
- else {
- isCommon = false;
- }
- }
- // Add the source value to the stack of traversed objects and associate
- // it with its merged value.
- stackA.push(srcValue);
- stackB.push(result);
-
- if (isCommon) {
- // Recursively merge objects and arrays (susceptible to call stack limits).
- object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
- } else if (result === result ? (result !== value) : (value === value)) {
- object[key] = result;
- }
+ function takeRightWhile(array, predicate, thisArg) {
+ return (array && array.length)
+ ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true)
+ : [];
}
/**
- * The base implementation of `_.property` without support for deep paths.
+ * Creates a slice of `array` with elements taken from the beginning. Elements
+ * are taken until `predicate` returns falsey. The predicate is bound to
+ * `thisArg` and invoked with three arguments: (value, index, array).
*
- * @private
- * @param {string} key The key of the property to get.
- * @returns {Function} Returns the new function.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeWhile([1, 2, 3], function(n) {
+ * return n < 3;
+ * });
+ * // => [1, 2]
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false},
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.takeWhile(users, { 'user': 'barney', 'active': false }), 'user');
+ * // => ['barney']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.takeWhile(users, 'active', false), 'user');
+ * // => ['barney', 'fred']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.takeWhile(users, 'active'), 'user');
+ * // => []
*/
- function baseProperty(key) {
- return function(object) {
- return object == null ? undefined : object[key];
- };
+ function takeWhile(array, predicate, thisArg) {
+ return (array && array.length)
+ ? baseWhile(array, getCallback(predicate, thisArg, 3))
+ : [];
}
/**
- * A specialized version of `baseProperty` which supports deep paths.
+ * Creates an array of unique values, in order, of the provided arrays using
+ * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+ * for equality comparisons.
*
- * @private
- * @param {Array|string} path The path of the property to get.
- * @returns {Function} Returns the new function.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.union([1, 2], [4, 2], [2, 1]);
+ * // => [1, 2, 4]
*/
- function basePropertyDeep(path) {
- var pathKey = (path + '');
- path = toPath(path);
- return function(object) {
- return baseGet(object, path, pathKey);
- };
- }
+ var union = restParam(function(arrays) {
+ return baseUniq(baseFlatten(arrays, false, true));
+ });
/**
- * The base implementation of `_.pullAt` without support for individual
- * index arguments and capturing the removed elements.
+ * Creates a duplicate-free version of an array, using
+ * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+ * for equality comparisons, in which only the first occurence of each element
+ * is kept. Providing `true` for `isSorted` performs a faster search algorithm
+ * for sorted arrays. If an iteratee function is provided it is invoked for
+ * each element in the array to generate the criterion by which uniqueness
+ * is computed. The `iteratee` is bound to `thisArg` and invoked with three
+ * arguments: (value, index, array).
*
- * @private
- * @param {Array} array The array to modify.
- * @param {number[]} indexes The indexes of elements to remove.
- * @returns {Array} Returns `array`.
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias unique
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {boolean} [isSorted] Specify the array is sorted.
+ * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new duplicate-value-free array.
+ * @example
+ *
+ * _.uniq([2, 1, 2]);
+ * // => [2, 1]
+ *
+ * // using `isSorted`
+ * _.uniq([1, 1, 2], true);
+ * // => [1, 2]
+ *
+ * // using an iteratee function
+ * _.uniq([1, 2.5, 1.5, 2], function(n) {
+ * return this.floor(n);
+ * }, Math);
+ * // => [1, 2.5]
+ *
+ * // using the `_.property` callback shorthand
+ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
*/
- function basePullAt(array, indexes) {
- var length = indexes.length;
- while (length--) {
- var index = parseFloat(indexes[length]);
- if (index != previous && isIndex(index)) {
- var previous = index;
- splice.call(array, index, 1);
- }
+ function uniq(array, isSorted, iteratee, thisArg) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
}
- return array;
+ if (isSorted != null && typeof isSorted != 'boolean') {
+ thisArg = iteratee;
+ iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted;
+ isSorted = false;
+ }
+ var func = getCallback();
+ if (!(func === baseCallback && iteratee == null)) {
+ iteratee = func(iteratee, thisArg, 3);
+ }
+ return (isSorted && getIndexOf() == baseIndexOf)
+ ? sortedUniq(array, iteratee)
+ : baseUniq(array, iteratee);
}
/**
- * The base implementation of `_.random` without support for argument juggling
- * and returning floating-point numbers.
+ * This method is like `_.zip` except that it accepts an array of grouped
+ * elements and creates an array regrouping the elements to their pre-zip
+ * configuration.
*
- * @private
- * @param {number} min The minimum possible value.
- * @param {number} max The maximum possible value.
- * @returns {number} Returns the random number.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
+ * // => [['fred', 30, true], ['barney', 40, false]]
+ *
+ * _.unzip(zipped);
+ * // => [['fred', 'barney'], [30, 40], [true, false]]
*/
- function baseRandom(min, max) {
- return min + floor(nativeRandom() * (max - min + 1));
+ function unzip(array) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var index = -1,
+ length = 0;
+
+ array = arrayFilter(array, function(group) {
+ if (isArrayLike(group)) {
+ length = nativeMax(group.length, length);
+ return true;
+ }
+ });
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = arrayMap(array, baseProperty(index));
+ }
+ return result;
}
/**
- * The base implementation of `_.reduce` and `_.reduceRight` without support
- * for callback shorthands and `this` binding, which iterates over `collection`
- * using the provided `eachFunc`.
+ * This method is like `_.unzip` except that it accepts an iteratee to specify
+ * how regrouped values should be combined. The `iteratee` is bound to `thisArg`
+ * and invoked with four arguments: (accumulator, value, index, group).
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {*} accumulator The initial value.
- * @param {boolean} initFromCollection Specify using the first or last element
- * of `collection` as the initial value.
- * @param {Function} eachFunc The function to iterate over `collection`.
- * @returns {*} Returns the accumulated value.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @param {Function} [iteratee] The function to combine regrouped values.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
+ * // => [[1, 10, 100], [2, 20, 200]]
+ *
+ * _.unzipWith(zipped, _.add);
+ * // => [3, 30, 300]
*/
- function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) {
- eachFunc(collection, function(value, index, collection) {
- accumulator = initFromCollection
- ? (initFromCollection = false, value)
- : iteratee(accumulator, value, index, collection);
+ function unzipWith(array, iteratee, thisArg) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ var result = unzip(array);
+ if (iteratee == null) {
+ return result;
+ }
+ iteratee = bindCallback(iteratee, thisArg, 4);
+ return arrayMap(result, function(group) {
+ return arrayReduce(group, iteratee, undefined, true);
});
- return accumulator;
}
/**
- * The base implementation of `setData` without support for hot loop detection.
+ * Creates an array excluding all provided values using
+ * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+ * for equality comparisons.
*
- * @private
- * @param {Function} func The function to associate metadata with.
- * @param {*} data The metadata.
- * @returns {Function} Returns `func`.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to filter.
+ * @param {...*} [values] The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.without([1, 2, 1, 3], 1, 2);
+ * // => [3]
*/
- var baseSetData = !metaMap ? identity : function(func, data) {
- metaMap.set(func, data);
- return func;
- };
+ var without = restParam(function(array, values) {
+ return isArrayLike(array)
+ ? baseDifference(array, values)
+ : [];
+ });
/**
- * The base implementation of `_.slice` without an iteratee call guard.
+ * Creates an array that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
+ * of the provided arrays.
*
- * @private
- * @param {Array} array The array to slice.
- * @param {number} [start=0] The start position.
- * @param {number} [end=array.length] The end position.
- * @returns {Array} Returns the slice of `array`.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of values.
+ * @example
+ *
+ * _.xor([1, 2], [4, 2]);
+ * // => [1, 4]
*/
- function baseSlice(array, start, end) {
+ function xor() {
var index = -1,
- length = array.length;
-
- start = start == null ? 0 : (+start || 0);
- if (start < 0) {
- start = -start > length ? 0 : (length + start);
- }
- end = (end === undefined || end > length) ? length : (+end || 0);
- if (end < 0) {
- end += length;
- }
- length = start > end ? 0 : ((end - start) >>> 0);
- start >>>= 0;
+ length = arguments.length;
- var result = Array(length);
while (++index < length) {
- result[index] = array[index + start];
+ var array = arguments[index];
+ if (isArrayLike(array)) {
+ var result = result
+ ? baseDifference(result, array).concat(baseDifference(array, result))
+ : array;
+ }
}
- return result;
+ return result ? baseUniq(result) : [];
}
/**
- * The base implementation of `_.some` without support for callback shorthands
- * and `this` binding.
+ * Creates an array of grouped elements, the first of which contains the first
+ * elements of the given arrays, the second of which contains the second elements
+ * of the given arrays, and so on.
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if any element passes the predicate check,
- * else `false`.
- */
- function baseSome(collection, predicate) {
- var result;
-
- baseEach(collection, function(value, index, collection) {
- result = predicate(value, index, collection);
- return !result;
- });
- return !!result;
- }
-
- /**
- * The base implementation of `_.sortBy` which uses `comparer` to define
- * the sort order of `array` and replaces criteria objects with their
- * corresponding values.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
*
- * @private
- * @param {Array} array The array to sort.
- * @param {Function} comparer The function to define sort order.
- * @returns {Array} Returns `array`.
+ * _.zip(['fred', 'barney'], [30, 40], [true, false]);
+ * // => [['fred', 30, true], ['barney', 40, false]]
*/
- function baseSortBy(array, comparer) {
- var length = array.length;
-
- array.sort(comparer);
- while (length--) {
- array[length] = array[length].value;
- }
- return array;
- }
+ var zip = restParam(unzip);
/**
- * The base implementation of `_.sortByOrder` without param guards.
+ * The inverse of `_.pairs`; this method returns an object composed from arrays
+ * of property names and values. Provide either a single two dimensional array,
+ * e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names
+ * and one of corresponding values.
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
- * @param {boolean[]} orders The sort orders of `iteratees`.
- * @returns {Array} Returns the new sorted array.
- */
- function baseSortByOrder(collection, iteratees, orders) {
- var callback = getCallback(),
- index = -1;
-
- iteratees = arrayMap(iteratees, function(iteratee) { return callback(iteratee); });
-
- var result = baseMap(collection, function(value) {
- var criteria = arrayMap(iteratees, function(iteratee) { return iteratee(value); });
- return { 'criteria': criteria, 'index': ++index, 'value': value };
- });
-
- return baseSortBy(result, function(object, other) {
- return compareMultiple(object, other, orders);
- });
- }
-
- /**
- * The base implementation of `_.sum` without support for callback shorthands
- * and `this` binding.
+ * @static
+ * @memberOf _
+ * @alias object
+ * @category Array
+ * @param {Array} props The property names.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {number} Returns the sum.
- */
- function baseSum(collection, iteratee) {
- var result = 0;
- baseEach(collection, function(value, index, collection) {
- result += +iteratee(value, index, collection) || 0;
- });
- return result;
- }
-
- /**
- * The base implementation of `_.uniq` without support for callback shorthands
- * and `this` binding.
+ * _.zipObject([['fred', 30], ['barney', 40]]);
+ * // => { 'fred': 30, 'barney': 40 }
*
- * @private
- * @param {Array} array The array to inspect.
- * @param {Function} [iteratee] The function invoked per iteration.
- * @returns {Array} Returns the new duplicate-value-free array.
+ * _.zipObject(['fred', 'barney'], [30, 40]);
+ * // => { 'fred': 30, 'barney': 40 }
*/
- function baseUniq(array, iteratee) {
+ function zipObject(props, values) {
var index = -1,
- indexOf = getIndexOf(),
- length = array.length,
- isCommon = indexOf == baseIndexOf,
- isLarge = isCommon && length >= 200,
- seen = isLarge ? createCache() : null,
- result = [];
+ length = props ? props.length : 0,
+ result = {};
- if (seen) {
- indexOf = cacheIndexOf;
- isCommon = false;
- } else {
- isLarge = false;
- seen = iteratee ? [] : result;
+ if (length && !values && !isArray(props[0])) {
+ values = [];
}
- outer:
while (++index < length) {
- var value = array[index],
- computed = iteratee ? iteratee(value, index, array) : value;
-
- if (isCommon && value === value) {
- var seenIndex = seen.length;
- while (seenIndex--) {
- if (seen[seenIndex] === computed) {
- continue outer;
- }
- }
- if (iteratee) {
- seen.push(computed);
- }
- result.push(value);
- }
- else if (indexOf(seen, computed, 0) < 0) {
- if (iteratee || isLarge) {
- seen.push(computed);
- }
- result.push(value);
+ var key = props[index];
+ if (values) {
+ result[key] = values[index];
+ } else if (key) {
+ result[key[0]] = key[1];
}
}
return result;
}
/**
- * The base implementation of `_.values` and `_.valuesIn` which creates an
- * array of `object` property values corresponding to the property names
- * of `props`.
+ * This method is like `_.zip` except that it accepts an iteratee to specify
+ * how grouped values should be combined. The `iteratee` is bound to `thisArg`
+ * and invoked with four arguments: (accumulator, value, index, group).
*
- * @private
- * @param {Object} object The object to query.
- * @param {Array} props The property names to get values for.
- * @returns {Object} Returns the array of property values.
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @param {Function} [iteratee] The function to combine grouped values.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zipWith([1, 2], [10, 20], [100, 200], _.add);
+ * // => [111, 222]
*/
- function baseValues(object, props) {
- var index = -1,
- length = props.length,
- result = Array(length);
+ var zipWith = restParam(function(arrays) {
+ var length = arrays.length,
+ iteratee = arrays[length - 2],
+ thisArg = arrays[length - 1];
- while (++index < length) {
- result[index] = object[props[index]];
+ if (length > 2 && typeof iteratee == 'function') {
+ length -= 2;
+ } else {
+ iteratee = (length > 1 && typeof thisArg == 'function') ? (--length, thisArg) : undefined;
+ thisArg = undefined;
}
- return result;
- }
+ arrays.length = length;
+ return unzipWith(arrays, iteratee, thisArg);
+ });
/**
- * The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`,
- * and `_.takeWhile` without support for callback shorthands and `this` binding.
+ * Creates a `lodash` object that wraps `value` with explicit method
+ * chaining enabled.
*
- * @private
- * @param {Array} array The array to query.
- * @param {Function} predicate The function invoked per iteration.
- * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
- * @param {boolean} [fromRight] Specify iterating from right to left.
- * @returns {Array} Returns the slice of `array`.
+ * @static
+ * @memberOf _
+ * @category Chain
+ * @param {*} value The value to wrap.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'pebbles', 'age': 1 }
+ * ];
+ *
+ * var youngest = _.chain(users)
+ * .sortBy('age')
+ * .map(function(chr) {
+ * return chr.user + ' is ' + chr.age;
+ * })
+ * .first()
+ * .value();
+ * // => 'pebbles is 1'
*/
- function baseWhile(array, predicate, isDrop, fromRight) {
- var length = array.length,
- index = fromRight ? length : -1;
-
- while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
- return isDrop
- ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
- : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
+ function chain(value) {
+ var result = lodash(value);
+ result.__chain__ = true;
+ return result;
}
/**
- * The base implementation of `wrapperValue` which returns the result of
- * performing a sequence of actions on the unwrapped `value`, where each
- * successive action is supplied the return value of the previous.
+ * This method invokes `interceptor` and returns `value`. The interceptor is
+ * bound to `thisArg` and invoked with one argument; (value). The purpose of
+ * this method is to "tap into" a method chain in order to perform operations
+ * on intermediate results within the chain.
*
- * @private
- * @param {*} value The unwrapped value.
- * @param {Array} actions Actions to peform to resolve the unwrapped value.
- * @returns {*} Returns the resolved value.
+ * @static
+ * @memberOf _
+ * @category Chain
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @param {*} [thisArg] The `this` binding of `interceptor`.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * _([1, 2, 3])
+ * .tap(function(array) {
+ * array.pop();
+ * })
+ * .reverse()
+ * .value();
+ * // => [2, 1]
*/
- function baseWrapperValue(value, actions) {
- var result = value;
- if (result instanceof LazyWrapper) {
- result = result.value();
- }
- var index = -1,
- length = actions.length;
-
- while (++index < length) {
- var args = [result],
- action = actions[index];
-
- push.apply(args, action.args);
- result = action.func.apply(action.thisArg, args);
- }
- return result;
+ function tap(value, interceptor, thisArg) {
+ interceptor.call(thisArg, value);
+ return value;
}
/**
- * Performs a binary search of `array` to determine the index at which `value`
- * should be inserted into `array` in order to maintain its sort order.
+ * This method is like `_.tap` except that it returns the result of `interceptor`.
*
- * @private
- * @param {Array} array The sorted array to inspect.
- * @param {*} value The value to evaluate.
- * @param {boolean} [retHighest] Specify returning the highest qualified index.
- * @returns {number} Returns the index at which `value` should be inserted
- * into `array`.
+ * @static
+ * @memberOf _
+ * @category Chain
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @param {*} [thisArg] The `this` binding of `interceptor`.
+ * @returns {*} Returns the result of `interceptor`.
+ * @example
+ *
+ * _(' abc ')
+ * .chain()
+ * .trim()
+ * .thru(function(value) {
+ * return [value];
+ * })
+ * .value();
+ * // => ['abc']
*/
- function binaryIndex(array, value, retHighest) {
- var low = 0,
- high = array ? array.length : low;
-
- if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
- while (low < high) {
- var mid = (low + high) >>> 1,
- computed = array[mid];
-
- if (retHighest ? (computed <= value) : (computed < value)) {
- low = mid + 1;
- } else {
- high = mid;
- }
- }
- return high;
- }
- return binaryIndexBy(array, value, identity, retHighest);
+ function thru(value, interceptor, thisArg) {
+ return interceptor.call(thisArg, value);
}
/**
- * This function is like `binaryIndex` except that it invokes `iteratee` for
- * `value` and each element of `array` to compute their sort ranking. The
- * iteratee is invoked with one argument; (value).
+ * Enables explicit method chaining on the wrapper object.
*
- * @private
- * @param {Array} array The sorted array to inspect.
- * @param {*} value The value to evaluate.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {boolean} [retHighest] Specify returning the highest qualified index.
- * @returns {number} Returns the index at which `value` should be inserted
- * into `array`.
+ * @name chain
+ * @memberOf _
+ * @category Chain
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * // without explicit chaining
+ * _(users).first();
+ * // => { 'user': 'barney', 'age': 36 }
+ *
+ * // with explicit chaining
+ * _(users).chain()
+ * .first()
+ * .pick('user')
+ * .value();
+ * // => { 'user': 'barney' }
*/
- function binaryIndexBy(array, value, iteratee, retHighest) {
- value = iteratee(value);
+ function wrapperChain() {
+ return chain(this);
+ }
- var low = 0,
- high = array ? array.length : 0,
- valIsNaN = value !== value,
- valIsUndef = value === undefined;
+ /**
+ * Executes the chained sequence and returns the wrapped result.
+ *
+ * @name commit
+ * @memberOf _
+ * @category Chain
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2];
+ * var wrapper = _(array).push(3);
+ *
+ * console.log(array);
+ * // => [1, 2]
+ *
+ * wrapper = wrapper.commit();
+ * console.log(array);
+ * // => [1, 2, 3]
+ *
+ * wrapper.last();
+ * // => 3
+ *
+ * console.log(array);
+ * // => [1, 2, 3]
+ */
+ function wrapperCommit() {
+ return new LodashWrapper(this.value(), this.__chain__);
+ }
- while (low < high) {
- var mid = floor((low + high) / 2),
- computed = iteratee(array[mid]),
- isReflexive = computed === computed;
+ /**
+ * Creates a clone of the chained sequence planting `value` as the wrapped value.
+ *
+ * @name plant
+ * @memberOf _
+ * @category Chain
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2];
+ * var wrapper = _(array).map(function(value) {
+ * return Math.pow(value, 2);
+ * });
+ *
+ * var other = [3, 4];
+ * var otherWrapper = wrapper.plant(other);
+ *
+ * otherWrapper.value();
+ * // => [9, 16]
+ *
+ * wrapper.value();
+ * // => [1, 4]
+ */
+ function wrapperPlant(value) {
+ var result,
+ parent = this;
- if (valIsNaN) {
- var setLow = isReflexive || retHighest;
- } else if (valIsUndef) {
- setLow = isReflexive && (retHighest || computed !== undefined);
- } else {
- setLow = retHighest ? (computed <= value) : (computed < value);
- }
- if (setLow) {
- low = mid + 1;
+ while (parent instanceof baseLodash) {
+ var clone = wrapperClone(parent);
+ if (result) {
+ previous.__wrapped__ = clone;
} else {
- high = mid;
+ result = clone;
}
+ var previous = clone;
+ parent = parent.__wrapped__;
}
- return nativeMin(high, MAX_ARRAY_INDEX);
+ previous.__wrapped__ = value;
+ return result;
}
/**
- * A specialized version of `baseCallback` which only supports `this` binding
- * and specifying the number of arguments to provide to `func`.
+ * Reverses the wrapped array so the first element becomes the last, the
+ * second element becomes the second to last, and so on.
*
- * @private
- * @param {Function} func The function to bind.
- * @param {*} thisArg The `this` binding of `func`.
- * @param {number} [argCount] The number of arguments to provide to `func`.
- * @returns {Function} Returns the callback.
+ * **Note:** This method mutates the wrapped array.
+ *
+ * @name reverse
+ * @memberOf _
+ * @category Chain
+ * @returns {Object} Returns the new reversed `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _(array).reverse().value()
+ * // => [3, 2, 1]
+ *
+ * console.log(array);
+ * // => [3, 2, 1]
*/
- function bindCallback(func, thisArg, argCount) {
- if (typeof func != 'function') {
- return identity;
- }
- if (thisArg === undefined) {
- return func;
- }
- switch (argCount) {
- case 1: return function(value) {
- return func.call(thisArg, value);
- };
- case 3: return function(value, index, collection) {
- return func.call(thisArg, value, index, collection);
- };
- case 4: return function(accumulator, value, index, collection) {
- return func.call(thisArg, accumulator, value, index, collection);
- };
- case 5: return function(value, other, key, object, source) {
- return func.call(thisArg, value, other, key, object, source);
- };
+ function wrapperReverse() {
+ var value = this.__wrapped__;
+ if (value instanceof LazyWrapper) {
+ if (this.__actions__.length) {
+ value = new LazyWrapper(this);
+ }
+ return new LodashWrapper(value.reverse(), this.__chain__);
}
- return function() {
- return func.apply(thisArg, arguments);
- };
+ return this.thru(function(value) {
+ return value.reverse();
+ });
}
/**
- * Creates a clone of the given array buffer.
+ * Produces the result of coercing the unwrapped value to a string.
*
- * @private
- * @param {ArrayBuffer} buffer The array buffer to clone.
- * @returns {ArrayBuffer} Returns the cloned array buffer.
+ * @name toString
+ * @memberOf _
+ * @category Chain
+ * @returns {string} Returns the coerced string value.
+ * @example
+ *
+ * _([1, 2, 3]).toString();
+ * // => '1,2,3'
*/
- function bufferClone(buffer) {
- return bufferSlice.call(buffer, 0);
- }
- if (!bufferSlice) {
- // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`.
- bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) {
- var byteLength = buffer.byteLength,
- floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0,
- offset = floatLength * FLOAT64_BYTES_PER_ELEMENT,
- result = new ArrayBuffer(byteLength);
-
- if (floatLength) {
- var view = new Float64Array(result, 0, floatLength);
- view.set(new Float64Array(buffer, 0, floatLength));
- }
- if (byteLength != offset) {
- view = new Uint8Array(result, offset);
- view.set(new Uint8Array(buffer, offset));
- }
- return result;
- };
+ function wrapperToString() {
+ return (this.value() + '');
}
/**
- * Creates an array that is the composition of partially applied arguments,
- * placeholders, and provided arguments into a single array of arguments.
+ * Executes the chained sequence to extract the unwrapped value.
*
- * @private
- * @param {Array|Object} args The provided arguments.
- * @param {Array} partials The arguments to prepend to those provided.
- * @param {Array} holders The `partials` placeholder indexes.
- * @returns {Array} Returns the new array of composed arguments.
+ * @name value
+ * @memberOf _
+ * @alias run, toJSON, valueOf
+ * @category Chain
+ * @returns {*} Returns the resolved unwrapped value.
+ * @example
+ *
+ * _([1, 2, 3]).value();
+ * // => [1, 2, 3]
*/
- function composeArgs(args, partials, holders) {
- var holdersLength = holders.length,
- argsIndex = -1,
- argsLength = nativeMax(args.length - holdersLength, 0),
- leftIndex = -1,
- leftLength = partials.length,
- result = Array(argsLength + leftLength);
-
- while (++leftIndex < leftLength) {
- result[leftIndex] = partials[leftIndex];
- }
- while (++argsIndex < holdersLength) {
- result[holders[argsIndex]] = args[argsIndex];
- }
- while (argsLength--) {
- result[leftIndex++] = args[argsIndex++];
- }
- return result;
+ function wrapperValue() {
+ return baseWrapperValue(this.__wrapped__, this.__actions__);
}
/**
- * This function is like `composeArgs` except that the arguments composition
- * is tailored for `_.partialRight`.
+ * Creates an array of elements corresponding to the given keys, or indexes,
+ * of `collection`. Keys may be specified as individual arguments or as arrays
+ * of keys.
*
- * @private
- * @param {Array|Object} args The provided arguments.
- * @param {Array} partials The arguments to append to those provided.
- * @param {Array} holders The `partials` placeholder indexes.
- * @returns {Array} Returns the new array of composed arguments.
- */
- function composeArgsRight(args, partials, holders) {
- var holdersIndex = -1,
- holdersLength = holders.length,
- argsIndex = -1,
- argsLength = nativeMax(args.length - holdersLength, 0),
- rightIndex = -1,
- rightLength = partials.length,
- result = Array(argsLength + rightLength);
-
- while (++argsIndex < argsLength) {
- result[argsIndex] = args[argsIndex];
- }
- var pad = argsIndex;
- while (++rightIndex < rightLength) {
- result[pad + rightIndex] = partials[rightIndex];
- }
- while (++holdersIndex < holdersLength) {
- result[pad + holders[holdersIndex]] = args[argsIndex++];
- }
- return result;
- }
-
- /**
- * Creates a function that aggregates a collection, creating an accumulator
- * object composed from the results of running each element in the collection
- * through an iteratee.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {...(number|number[]|string|string[])} [props] The property names
+ * or indexes of elements to pick, specified individually or in arrays.
+ * @returns {Array} Returns the new array of picked elements.
+ * @example
*
- * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`,
- * and `_.partition`.
+ * _.at(['a', 'b', 'c'], [0, 2]);
+ * // => ['a', 'c']
*
- * @private
- * @param {Function} setter The function to set keys and values of the accumulator object.
- * @param {Function} [initializer] The function to initialize the accumulator object.
- * @returns {Function} Returns the new aggregator function.
+ * _.at(['barney', 'fred', 'pebbles'], 0, 2);
+ * // => ['barney', 'pebbles']
*/
- function createAggregator(setter, initializer) {
- return function(collection, iteratee, thisArg) {
- var result = initializer ? initializer() : {};
- iteratee = getCallback(iteratee, thisArg, 3);
-
- if (isArray(collection)) {
- var index = -1,
- length = collection.length;
-
- while (++index < length) {
- var value = collection[index];
- setter(result, value, iteratee(value, index, collection), collection);
- }
- } else {
- baseEach(collection, function(value, key, collection) {
- setter(result, value, iteratee(value, key, collection), collection);
- });
- }
- return result;
- };
- }
+ var at = restParam(function(collection, props) {
+ return baseAt(collection, baseFlatten(props));
+ });
/**
- * Creates a function that assigns properties of source object(s) to a given
- * destination object.
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is the number of times the key was returned by `iteratee`.
+ * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
*
- * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`.
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
*
- * @private
- * @param {Function} assigner The function to assign values.
- * @returns {Function} Returns the new assigner function.
- */
- function createAssigner(assigner) {
- return restParam(function(object, sources) {
- var index = -1,
- length = object == null ? 0 : sources.length,
- customizer = length > 2 && sources[length - 2],
- guard = length > 2 && sources[2],
- thisArg = length > 1 && sources[length - 1];
-
- if (typeof customizer == 'function') {
- customizer = bindCallback(customizer, thisArg, 5);
- length -= 2;
- } else {
- customizer = typeof thisArg == 'function' ? thisArg : null;
- length -= (customizer ? 1 : 0);
- }
- if (guard && isIterateeCall(sources[0], sources[1], guard)) {
- customizer = length < 3 ? null : customizer;
- length = 1;
- }
- while (++index < length) {
- var source = sources[index];
- if (source) {
- assigner(object, source, customizer);
- }
- }
- return object;
- });
- }
-
- /**
- * Creates a `baseEach` or `baseEachRight` function.
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
*
- * @private
- * @param {Function} eachFunc The function to iterate over a collection.
- * @param {boolean} [fromRight] Specify iterating from right to left.
- * @returns {Function} Returns the new base function.
- */
- function createBaseEach(eachFunc, fromRight) {
- return function(collection, iteratee) {
- var length = collection ? getLength(collection) : 0;
- if (!isLength(length)) {
- return eachFunc(collection, iteratee);
- }
- var index = fromRight ? length : -1,
- iterable = toObject(collection);
-
- while ((fromRight ? index-- : ++index < length)) {
- if (iteratee(iterable[index], index, iterable) === false) {
- break;
- }
- }
- return collection;
- };
- }
-
- /**
- * Creates a base function for `_.forIn` or `_.forInRight`.
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
*
- * @private
- * @param {boolean} [fromRight] Specify iterating from right to left.
- * @returns {Function} Returns the new base function.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.countBy([4.3, 6.1, 6.4], function(n) {
+ * return Math.floor(n);
+ * });
+ * // => { '4': 1, '6': 2 }
+ *
+ * _.countBy([4.3, 6.1, 6.4], function(n) {
+ * return this.floor(n);
+ * }, Math);
+ * // => { '4': 1, '6': 2 }
+ *
+ * _.countBy(['one', 'two', 'three'], 'length');
+ * // => { '3': 2, '5': 1 }
*/
- function createBaseFor(fromRight) {
- return function(object, iteratee, keysFunc) {
- var iterable = toObject(object),
- props = keysFunc(object),
- length = props.length,
- index = fromRight ? length : -1;
-
- while ((fromRight ? index-- : ++index < length)) {
- var key = props[index];
- if (iteratee(iterable[key], key, iterable) === false) {
- break;
- }
- }
- return object;
- };
- }
+ var countBy = createAggregator(function(result, value, key) {
+ hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
+ });
/**
- * Creates a function that wraps `func` and invokes it with the `this`
- * binding of `thisArg`.
+ * Checks if `predicate` returns truthy for **all** elements of `collection`.
+ * The predicate is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
*
- * @private
- * @param {Function} func The function to bind.
- * @param {*} [thisArg] The `this` binding of `func`.
- * @returns {Function} Returns the new bound function.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias all
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ * @example
+ *
+ * _.every([true, 1, null, 'yes'], Boolean);
+ * // => false
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.every(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.every(users, 'active', false);
+ * // => true
+ *
+ * // using the `_.property` callback shorthand
+ * _.every(users, 'active');
+ * // => false
*/
- function createBindWrapper(func, thisArg) {
- var Ctor = createCtorWrapper(func);
-
- function wrapper() {
- var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
- return fn.apply(thisArg, arguments);
+ function every(collection, predicate, thisArg) {
+ var func = isArray(collection) ? arrayEvery : baseEvery;
+ if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
+ predicate = null;
}
- return wrapper;
+ if (typeof predicate != 'function' || thisArg !== undefined) {
+ predicate = getCallback(predicate, thisArg, 3);
+ }
+ return func(collection, predicate);
}
/**
- * Creates a `Set` cache object to optimize linear searches of large arrays.
- *
- * @private
- * @param {Array} [values] The values to cache.
- * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`.
- */
- var createCache = !(nativeCreate && Set) ? constant(null) : function(values) {
- return new SetCache(values);
- };
-
- /**
- * Creates a function that produces compound words out of the words in a
- * given string.
+ * Iterates over elements of `collection`, returning an array of all elements
+ * `predicate` returns truthy for. The predicate is bound to `thisArg` and
+ * invoked with three arguments: (value, index|key, collection).
*
- * @private
- * @param {Function} callback The function to combine each word.
- * @returns {Function} Returns the new compounder function.
- */
- function createCompounder(callback) {
- return function(string) {
- var index = -1,
- array = words(deburr(string)),
- length = array.length,
- result = '';
-
- while (++index < length) {
- result = callback(result, array[index], index);
- }
- return result;
- };
- }
-
- /**
- * Creates a function that produces an instance of `Ctor` regardless of
- * whether it was invoked as part of a `new` expression or by `call` or `apply`.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
*
- * @private
- * @param {Function} Ctor The constructor to wrap.
- * @returns {Function} Returns the new wrapped function.
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias select
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the new filtered array.
+ * @example
+ *
+ * _.filter([4, 5, 6], function(n) {
+ * return n % 2 == 0;
+ * });
+ * // => [4, 6]
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');
+ * // => ['barney']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.filter(users, 'active', false), 'user');
+ * // => ['fred']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.filter(users, 'active'), 'user');
+ * // => ['barney']
*/
- function createCtorWrapper(Ctor) {
- return function() {
- var thisBinding = baseCreate(Ctor.prototype),
- result = Ctor.apply(thisBinding, arguments);
-
- // Mimic the constructor's `return` behavior.
- // See https://es5.github.io/#x13.2.2 for more details.
- return isObject(result) ? result : thisBinding;
- };
+ function filter(collection, predicate, thisArg) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ predicate = getCallback(predicate, thisArg, 3);
+ return func(collection, predicate);
}
/**
- * Creates a `_.curry` or `_.curryRight` function.
+ * Iterates over elements of `collection`, returning the first element
+ * `predicate` returns truthy for. The predicate is bound to `thisArg` and
+ * invoked with three arguments: (value, index|key, collection).
*
- * @private
- * @param {boolean} flag The curry bit flag.
- * @returns {Function} Returns the new curry function.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias detect
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false },
+ * { 'user': 'pebbles', 'age': 1, 'active': true }
+ * ];
+ *
+ * _.result(_.find(users, function(chr) {
+ * return chr.age < 40;
+ * }), 'user');
+ * // => 'barney'
+ *
+ * // using the `_.matches` callback shorthand
+ * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');
+ * // => 'pebbles'
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.result(_.find(users, 'active', false), 'user');
+ * // => 'fred'
+ *
+ * // using the `_.property` callback shorthand
+ * _.result(_.find(users, 'active'), 'user');
+ * // => 'barney'
*/
- function createCurry(flag) {
- function curryFunc(func, arity, guard) {
- if (guard && isIterateeCall(func, arity, guard)) {
- arity = null;
- }
- var result = createWrapper(func, flag, null, null, null, null, null, arity);
- result.placeholder = curryFunc.placeholder;
- return result;
- }
- return curryFunc;
- }
+ var find = createFind(baseEach);
/**
- * Creates a `_.max` or `_.min` function.
+ * This method is like `_.find` except that it iterates over elements of
+ * `collection` from right to left.
*
- * @private
- * @param {Function} arrayFunc The function to get the extremum value from an array.
- * @param {boolean} [isMin] Specify returning the minimum, instead of the maximum,
- * extremum value.
- * @returns {Function} Returns the new extremum function.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * _.findLast([1, 2, 3, 4], function(n) {
+ * return n % 2 == 1;
+ * });
+ * // => 3
*/
- function createExtremum(arrayFunc, isMin) {
- return function(collection, iteratee, thisArg) {
- if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
- iteratee = null;
- }
- var func = getCallback(),
- noIteratee = iteratee == null;
-
- if (!(func === baseCallback && noIteratee)) {
- noIteratee = false;
- iteratee = func(iteratee, thisArg, 3);
- }
- if (noIteratee) {
- var isArr = isArray(collection);
- if (!isArr && isString(collection)) {
- iteratee = charAtCallback;
- } else {
- return arrayFunc(isArr ? collection : toIterable(collection));
- }
- }
- return extremumBy(collection, iteratee, isMin);
- };
- }
+ var findLast = createFind(baseEachRight, true);
/**
- * Creates a `_.find` or `_.findLast` function.
+ * Performs a deep comparison between each element in `collection` and the
+ * source object, returning the first element that has equivalent property
+ * values.
*
- * @private
- * @param {Function} eachFunc The function to iterate over a collection.
- * @param {boolean} [fromRight] Specify iterating from right to left.
- * @returns {Function} Returns the new find function.
+ * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+ * numbers, `Object` objects, regexes, and strings. Objects are compared by
+ * their own, not inherited, enumerable properties. For comparing a single
+ * own or inherited property value see `_.matchesProperty`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Object} source The object of property values to match.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * _.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user');
+ * // => 'barney'
+ *
+ * _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user');
+ * // => 'fred'
*/
- function createFind(eachFunc, fromRight) {
- return function(collection, predicate, thisArg) {
- predicate = getCallback(predicate, thisArg, 3);
- if (isArray(collection)) {
- var index = baseFindIndex(collection, predicate, fromRight);
- return index > -1 ? collection[index] : undefined;
- }
- return baseFind(collection, predicate, eachFunc);
- }
+ function findWhere(collection, source) {
+ return find(collection, baseMatches(source));
}
/**
- * Creates a `_.findIndex` or `_.findLastIndex` function.
+ * Iterates over elements of `collection` invoking `iteratee` for each element.
+ * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection). Iteratee functions may exit iteration early
+ * by explicitly returning `false`.
*
- * @private
- * @param {boolean} [fromRight] Specify iterating from right to left.
- * @returns {Function} Returns the new find function.
- */
- function createFindIndex(fromRight) {
- return function(array, predicate, thisArg) {
- if (!(array && array.length)) {
- return -1;
- }
- predicate = getCallback(predicate, thisArg, 3);
- return baseFindIndex(array, predicate, fromRight);
- };
- }
-
- /**
- * Creates a `_.findKey` or `_.findLastKey` function.
+ * **Note:** As with other "Collections" methods, objects with a "length" property
+ * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
+ * may be used for object iteration.
*
- * @private
- * @param {Function} objectFunc The function to iterate over an object.
- * @returns {Function} Returns the new find function.
- */
- function createFindKey(objectFunc) {
- return function(object, predicate, thisArg) {
- predicate = getCallback(predicate, thisArg, 3);
- return baseFind(object, predicate, objectFunc, true);
- };
- }
-
- /**
- * Creates a `_.flow` or `_.flowRight` function.
+ * @static
+ * @memberOf _
+ * @alias each
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array|Object|string} Returns `collection`.
+ * @example
*
- * @private
- * @param {boolean} [fromRight] Specify iterating from right to left.
- * @returns {Function} Returns the new flow function.
- */
- function createFlow(fromRight) {
- return function() {
- var length = arguments.length;
- if (!length) {
- return function() { return arguments[0]; };
- }
- var wrapper,
- index = fromRight ? length : -1,
- leftIndex = 0,
- funcs = Array(length);
-
- while ((fromRight ? index-- : ++index < length)) {
- var func = funcs[leftIndex++] = arguments[index];
- if (typeof func != 'function') {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- var funcName = wrapper ? '' : getFuncName(func);
- wrapper = funcName == 'wrapper' ? new LodashWrapper([]) : wrapper;
- }
- index = wrapper ? -1 : length;
- while (++index < length) {
- func = funcs[index];
- funcName = getFuncName(func);
-
- var data = funcName == 'wrapper' ? getData(func) : null;
- if (data && isLaziable(data[0])) {
- wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
- } else {
- wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
- }
- }
- return function() {
- var args = arguments;
- if (wrapper && args.length == 1 && isArray(args[0])) {
- return wrapper.plant(args[0]).value();
- }
- var index = 0,
- result = funcs[index].apply(this, args);
-
- while (++index < length) {
- result = funcs[index].call(this, result);
- }
- return result;
- };
- };
- }
-
- /**
- * Creates a function for `_.forEach` or `_.forEachRight`.
+ * _([1, 2]).forEach(function(n) {
+ * console.log(n);
+ * }).value();
+ * // => logs each value from left to right and returns the array
*
- * @private
- * @param {Function} arrayFunc The function to iterate over an array.
- * @param {Function} eachFunc The function to iterate over a collection.
- * @returns {Function} Returns the new each function.
+ * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
+ * console.log(n, key);
+ * });
+ * // => logs each value-key pair and returns the object (iteration order is not guaranteed)
*/
- function createForEach(arrayFunc, eachFunc) {
- return function(collection, iteratee, thisArg) {
- return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
- ? arrayFunc(collection, iteratee)
- : eachFunc(collection, bindCallback(iteratee, thisArg, 3));
- };
- }
+ var forEach = createForEach(arrayEach, baseEach);
/**
- * Creates a function for `_.forIn` or `_.forInRight`.
+ * This method is like `_.forEach` except that it iterates over elements of
+ * `collection` from right to left.
*
- * @private
- * @param {Function} objectFunc The function to iterate over an object.
- * @returns {Function} Returns the new each function.
- */
- function createForIn(objectFunc) {
- return function(object, iteratee, thisArg) {
- if (typeof iteratee != 'function' || thisArg !== undefined) {
- iteratee = bindCallback(iteratee, thisArg, 3);
- }
- return objectFunc(object, iteratee, keysIn);
- };
- }
-
- /**
- * Creates a function for `_.forOwn` or `_.forOwnRight`.
+ * @static
+ * @memberOf _
+ * @alias eachRight
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array|Object|string} Returns `collection`.
+ * @example
*
- * @private
- * @param {Function} objectFunc The function to iterate over an object.
- * @returns {Function} Returns the new each function.
+ * _([1, 2]).forEachRight(function(n) {
+ * console.log(n);
+ * }).value();
+ * // => logs each value from right to left and returns the array
*/
- function createForOwn(objectFunc) {
- return function(object, iteratee, thisArg) {
- if (typeof iteratee != 'function' || thisArg !== undefined) {
- iteratee = bindCallback(iteratee, thisArg, 3);
- }
- return objectFunc(object, iteratee);
- };
- }
+ var forEachRight = createForEach(arrayEachRight, baseEachRight);
/**
- * Creates a function for `_.padLeft` or `_.padRight`.
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is an array of the elements responsible for generating the key.
+ * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
*
- * @private
- * @param {boolean} [fromRight] Specify padding from the right.
- * @returns {Function} Returns the new pad function.
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.groupBy([4.2, 6.1, 6.4], function(n) {
+ * return Math.floor(n);
+ * });
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
+ *
+ * _.groupBy([4.2, 6.1, 6.4], function(n) {
+ * return this.floor(n);
+ * }, Math);
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
+ *
+ * // using the `_.property` callback shorthand
+ * _.groupBy(['one', 'two', 'three'], 'length');
+ * // => { '3': ['one', 'two'], '5': ['three'] }
*/
- function createPadDir(fromRight) {
- return function(string, length, chars) {
- string = baseToString(string);
- return string && ((fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string));
- };
- }
+ var groupBy = createAggregator(function(result, value, key) {
+ if (hasOwnProperty.call(result, key)) {
+ result[key].push(value);
+ } else {
+ result[key] = [value];
+ }
+ });
/**
- * Creates a `_.partial` or `_.partialRight` function.
+ * Checks if `value` is in `collection` using
+ * [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+ * for equality comparisons. If `fromIndex` is negative, it is used as the offset
+ * from the end of `collection`.
*
- * @private
- * @param {boolean} flag The partial bit flag.
- * @returns {Function} Returns the new partial function.
+ * @static
+ * @memberOf _
+ * @alias contains, include
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {*} target The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
+ * @returns {boolean} Returns `true` if a matching element is found, else `false`.
+ * @example
+ *
+ * _.includes([1, 2, 3], 1);
+ * // => true
+ *
+ * _.includes([1, 2, 3], 1, 2);
+ * // => false
+ *
+ * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
+ * // => true
+ *
+ * _.includes('pebbles', 'eb');
+ * // => true
*/
- function createPartial(flag) {
- var partialFunc = restParam(function(func, partials) {
- var holders = replaceHolders(partials, partialFunc.placeholder);
- return createWrapper(func, flag, null, partials, holders);
- });
- return partialFunc;
+ function includes(collection, target, fromIndex, guard) {
+ var length = collection ? getLength(collection) : 0;
+ if (!isLength(length)) {
+ collection = values(collection);
+ length = collection.length;
+ }
+ if (!length) {
+ return false;
+ }
+ if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
+ fromIndex = 0;
+ } else {
+ fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
+ }
+ return (typeof collection == 'string' || !isArray(collection) && isString(collection))
+ ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1)
+ : (getIndexOf(collection, target, fromIndex) > -1);
}
/**
- * Creates a function for `_.reduce` or `_.reduceRight`.
- *
- * @private
- * @param {Function} arrayFunc The function to iterate over an array.
- * @param {Function} eachFunc The function to iterate over a collection.
- * @returns {Function} Returns the new each function.
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is the last element responsible for generating the key. The
+ * iteratee function is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * var keyData = [
+ * { 'dir': 'left', 'code': 97 },
+ * { 'dir': 'right', 'code': 100 }
+ * ];
+ *
+ * _.indexBy(keyData, 'dir');
+ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+ *
+ * _.indexBy(keyData, function(object) {
+ * return String.fromCharCode(object.code);
+ * });
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+ *
+ * _.indexBy(keyData, function(object) {
+ * return this.fromCharCode(object.code);
+ * }, String);
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*/
- function createReduce(arrayFunc, eachFunc) {
- return function(collection, iteratee, accumulator, thisArg) {
- var initFromArray = arguments.length < 3;
- return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
- ? arrayFunc(collection, iteratee, accumulator, initFromArray)
- : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);
- };
- }
+ var indexBy = createAggregator(function(result, value, key) {
+ result[key] = value;
+ });
/**
- * Creates a function that wraps `func` and invokes it with optional `this`
- * binding of, partial application, and currying.
+ * Invokes the method at `path` on each element in `collection`, returning
+ * an array of the results of each invoked method. Any additional arguments
+ * are provided to each invoked method. If `methodName` is a function it is
+ * invoked for, and `this` bound to, each element in `collection`.
*
- * @private
- * @param {Function|string} func The function or method name to reference.
- * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
- * @param {*} [thisArg] The `this` binding of `func`.
- * @param {Array} [partials] The arguments to prepend to those provided to the new function.
- * @param {Array} [holders] The `partials` placeholder indexes.
- * @param {Array} [partialsRight] The arguments to append to those provided to the new function.
- * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
- * @param {Array} [argPos] The argument positions of the new function.
- * @param {number} [ary] The arity cap of `func`.
- * @param {number} [arity] The arity of `func`.
- * @returns {Function} Returns the new wrapped function.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Array|Function|string} path The path of the method to invoke or
+ * the function invoked per iteration.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {Array} Returns the array of results.
+ * @example
+ *
+ * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+ * // => [[1, 5, 7], [1, 2, 3]]
+ *
+ * _.invoke([123, 456], String.prototype.split, '');
+ * // => [['1', '2', '3'], ['4', '5', '6']]
*/
- function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
- var isAry = bitmask & ARY_FLAG,
- isBind = bitmask & BIND_FLAG,
- isBindKey = bitmask & BIND_KEY_FLAG,
- isCurry = bitmask & CURRY_FLAG,
- isCurryBound = bitmask & CURRY_BOUND_FLAG,
- isCurryRight = bitmask & CURRY_RIGHT_FLAG;
-
- var Ctor = !isBindKey && createCtorWrapper(func),
- key = func;
-
- function wrapper() {
- // Avoid `arguments` object use disqualifying optimizations by
- // converting it to an array before providing it to other functions.
- var length = arguments.length,
- index = length,
- args = Array(length);
-
- while (index--) {
- args[index] = arguments[index];
- }
- if (partials) {
- args = composeArgs(args, partials, holders);
- }
- if (partialsRight) {
- args = composeArgsRight(args, partialsRight, holdersRight);
- }
- if (isCurry || isCurryRight) {
- var placeholder = wrapper.placeholder,
- argsHolders = replaceHolders(args, placeholder);
-
- length -= argsHolders.length;
- if (length < arity) {
- var newArgPos = argPos ? arrayCopy(argPos) : null,
- newArity = nativeMax(arity - length, 0),
- newsHolders = isCurry ? argsHolders : null,
- newHoldersRight = isCurry ? null : argsHolders,
- newPartials = isCurry ? args : null,
- newPartialsRight = isCurry ? null : args;
-
- bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
- bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
-
- if (!isCurryBound) {
- bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
- }
- var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],
- result = createHybridWrapper.apply(undefined, newData);
+ var invoke = restParam(function(collection, path, args) {
+ var index = -1,
+ isFunc = typeof path == 'function',
+ isProp = isKey(path),
+ result = isArrayLike(collection) ? Array(collection.length) : [];
- if (isLaziable(func)) {
- setData(result, newData);
- }
- result.placeholder = placeholder;
- return result;
- }
- }
- var thisBinding = isBind ? thisArg : this;
- if (isBindKey) {
- func = thisBinding[key];
- }
- if (argPos) {
- args = reorder(args, argPos);
- }
- if (isAry && ary < args.length) {
- args.length = ary;
- }
- var fn = (this && this !== root && this instanceof wrapper) ? (Ctor || createCtorWrapper(func)) : func;
- return fn.apply(thisBinding, args);
- }
- return wrapper;
- }
+ baseEach(collection, function(value) {
+ var func = isFunc ? path : (isProp && value != null && value[path]);
+ result[++index] = func ? func.apply(value, args) : invokePath(value, path, args);
+ });
+ return result;
+ });
/**
- * Creates the padding required for `string` based on the given `length`.
- * The `chars` string is truncated if the number of characters exceeds `length`.
+ * Creates an array of values by running each element in `collection` through
+ * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three
+ * arguments: (value, index|key, collection).
*
- * @private
- * @param {string} string The string to create padding for.
- * @param {number} [length=0] The padding length.
- * @param {string} [chars=' '] The string used as padding.
- * @returns {string} Returns the pad for `string`.
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * Many lodash methods are guarded to work as interatees for methods like
+ * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
+ *
+ * The guarded methods are:
+ * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`,
+ * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`,
+ * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`,
+ * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`,
+ * `sum`, `uniq`, and `words`
+ *
+ * @static
+ * @memberOf _
+ * @alias collect
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new mapped array.
+ * @example
+ *
+ * function timesThree(n) {
+ * return n * 3;
+ * }
+ *
+ * _.map([1, 2], timesThree);
+ * // => [3, 6]
+ *
+ * _.map({ 'a': 1, 'b': 2 }, timesThree);
+ * // => [3, 6] (iteration order is not guaranteed)
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * // using the `_.property` callback shorthand
+ * _.map(users, 'user');
+ * // => ['barney', 'fred']
*/
- function createPadding(string, length, chars) {
- var strLength = string.length;
- length = +length;
-
- if (strLength >= length || !nativeIsFinite(length)) {
- return '';
- }
- var padLength = length - strLength;
- chars = chars == null ? ' ' : (chars + '');
- return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength);
+ function map(collection, iteratee, thisArg) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ iteratee = getCallback(iteratee, thisArg, 3);
+ return func(collection, iteratee);
}
/**
- * Creates a function that wraps `func` and invokes it with the optional `this`
- * binding of `thisArg` and the `partials` prepended to those provided to
- * the wrapper.
+ * Creates an array of elements split into two groups, the first of which
+ * contains elements `predicate` returns truthy for, while the second of which
+ * contains elements `predicate` returns falsey for. The predicate is bound
+ * to `thisArg` and invoked with three arguments: (value, index|key, collection).
*
- * @private
- * @param {Function} func The function to partially apply arguments to.
- * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
- * @param {*} thisArg The `this` binding of `func`.
- * @param {Array} partials The arguments to prepend to those provided to the new function.
- * @returns {Function} Returns the new bound function.
- */
- function createPartialWrapper(func, bitmask, thisArg, partials) {
- var isBind = bitmask & BIND_FLAG,
- Ctor = createCtorWrapper(func);
-
- function wrapper() {
- // Avoid `arguments` object use disqualifying optimizations by
- // converting it to an array before providing it `func`.
- var argsIndex = -1,
- argsLength = arguments.length,
- leftIndex = -1,
- leftLength = partials.length,
- args = Array(argsLength + leftLength);
-
- while (++leftIndex < leftLength) {
- args[leftIndex] = partials[leftIndex];
- }
- while (argsLength--) {
- args[leftIndex++] = arguments[++argsIndex];
- }
- var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
- return fn.apply(isBind ? thisArg : this, args);
- }
- return wrapper;
- }
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the array of grouped elements.
+ * @example
+ *
+ * _.partition([1, 2, 3], function(n) {
+ * return n % 2;
+ * });
+ * // => [[1, 3], [2]]
+ *
+ * _.partition([1.2, 2.3, 3.4], function(n) {
+ * return this.floor(n) % 2;
+ * }, Math);
+ * // => [[1.2, 3.4], [2.3]]
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true },
+ * { 'user': 'pebbles', 'age': 1, 'active': false }
+ * ];
+ *
+ * var mapper = function(array) {
+ * return _.pluck(array, 'user');
+ * };
+ *
+ * // using the `_.matches` callback shorthand
+ * _.map(_.partition(users, { 'age': 1, 'active': false }), mapper);
+ * // => [['pebbles'], ['barney', 'fred']]
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.map(_.partition(users, 'active', false), mapper);
+ * // => [['barney', 'pebbles'], ['fred']]
+ *
+ * // using the `_.property` callback shorthand
+ * _.map(_.partition(users, 'active'), mapper);
+ * // => [['fred'], ['barney', 'pebbles']]
+ */
+ var partition = createAggregator(function(result, value, key) {
+ result[key ? 0 : 1].push(value);
+ }, function() { return [[], []]; });
/**
- * Creates a `_.sortedIndex` or `_.sortedLastIndex` function.
+ * Gets the property value of `path` from all elements in `collection`.
*
- * @private
- * @param {boolean} [retHighest] Specify returning the highest qualified index.
- * @returns {Function} Returns the new index function.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Array|string} path The path of the property to pluck.
+ * @returns {Array} Returns the property values.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * _.pluck(users, 'user');
+ * // => ['barney', 'fred']
+ *
+ * var userIndex = _.indexBy(users, 'user');
+ * _.pluck(userIndex, 'age');
+ * // => [36, 40] (iteration order is not guaranteed)
*/
- function createSortedIndex(retHighest) {
- return function(array, value, iteratee, thisArg) {
- var func = getCallback(iteratee);
- return (func === baseCallback && iteratee == null)
- ? binaryIndex(array, value, retHighest)
- : binaryIndexBy(array, value, func(iteratee, thisArg, 1), retHighest);
- };
+ function pluck(collection, path) {
+ return map(collection, property(path));
}
/**
- * Creates a function that either curries or invokes `func` with optional
- * `this` binding and partially applied arguments.
+ * Reduces `collection` to a value which is the accumulated result of running
+ * each element in `collection` through `iteratee`, where each successive
+ * invocation is supplied the return value of the previous. If `accumulator`
+ * is not provided the first element of `collection` is used as the initial
+ * value. The `iteratee` is bound to `thisArg` and invoked with four arguments:
+ * (accumulator, value, index|key, collection).
*
- * @private
- * @param {Function|string} func The function or method name to reference.
- * @param {number} bitmask The bitmask of flags.
- * The bitmask may be composed of the following flags:
- * 1 - `_.bind`
- * 2 - `_.bindKey`
- * 4 - `_.curry` or `_.curryRight` of a bound function
- * 8 - `_.curry`
- * 16 - `_.curryRight`
- * 32 - `_.partial`
- * 64 - `_.partialRight`
- * 128 - `_.rearg`
- * 256 - `_.ary`
- * @param {*} [thisArg] The `this` binding of `func`.
- * @param {Array} [partials] The arguments to be partially applied.
- * @param {Array} [holders] The `partials` placeholder indexes.
- * @param {Array} [argPos] The argument positions of the new function.
- * @param {number} [ary] The arity cap of `func`.
- * @param {number} [arity] The arity of `func`.
- * @returns {Function} Returns the new wrapped function.
+ * Many lodash methods are guarded to work as interatees for methods like
+ * `_.reduce`, `_.reduceRight`, and `_.transform`.
+ *
+ * The guarded methods are:
+ * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder`
+ *
+ * @static
+ * @memberOf _
+ * @alias foldl, inject
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * _.reduce([1, 2], function(total, n) {
+ * return total + n;
+ * });
+ * // => 3
+ *
+ * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {
+ * result[key] = n * 3;
+ * return result;
+ * }, {});
+ * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed)
*/
- function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
- var isBindKey = bitmask & BIND_KEY_FLAG;
- if (!isBindKey && typeof func != 'function') {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- var length = partials ? partials.length : 0;
- if (!length) {
- bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
- partials = holders = null;
- }
- length -= (holders ? holders.length : 0);
- if (bitmask & PARTIAL_RIGHT_FLAG) {
- var partialsRight = partials,
- holdersRight = holders;
-
- partials = holders = null;
- }
- var data = isBindKey ? null : getData(func),
- newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
-
- if (data) {
- mergeData(newData, data);
- bitmask = newData[1];
- arity = newData[9];
- }
- newData[9] = arity == null
- ? (isBindKey ? 0 : func.length)
- : (nativeMax(arity - length, 0) || 0);
-
- if (bitmask == BIND_FLAG) {
- var result = createBindWrapper(newData[0], newData[2]);
- } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {
- result = createPartialWrapper.apply(undefined, newData);
- } else {
- result = createHybridWrapper.apply(undefined, newData);
- }
- var setter = data ? baseSetData : setData;
- return setter(result, newData);
- }
+ var reduce = createReduce(arrayReduce, baseEach);
/**
- * A specialized version of `baseIsEqualDeep` for arrays with support for
- * partial deep comparisons.
+ * This method is like `_.reduce` except that it iterates over elements of
+ * `collection` from right to left.
*
- * @private
- * @param {Array} array The array to compare.
- * @param {Array} other The other array to compare.
- * @param {Function} equalFunc The function to determine equivalents of values.
- * @param {Function} [customizer] The function to customize comparing arrays.
- * @param {boolean} [isLoose] Specify performing partial comparisons.
- * @param {Array} [stackA] Tracks traversed `value` objects.
- * @param {Array} [stackB] Tracks traversed `other` objects.
- * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
+ * @static
+ * @memberOf _
+ * @alias foldr
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * var array = [[0, 1], [2, 3], [4, 5]];
+ *
+ * _.reduceRight(array, function(flattened, other) {
+ * return flattened.concat(other);
+ * }, []);
+ * // => [4, 5, 2, 3, 0, 1]
*/
- function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
- var index = -1,
- arrLength = array.length,
- othLength = other.length,
- result = true;
-
- if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
- return false;
- }
- // Deep compare the contents, ignoring non-numeric properties.
- while (result && ++index < arrLength) {
- var arrValue = array[index],
- othValue = other[index];
-
- result = undefined;
- if (customizer) {
- result = isLoose
- ? customizer(othValue, arrValue, index)
- : customizer(arrValue, othValue, index);
- }
- if (result === undefined) {
- // Recursively compare arrays (susceptible to call stack limits).
- if (isLoose) {
- var othIndex = othLength;
- while (othIndex--) {
- othValue = other[othIndex];
- result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
- if (result) {
- break;
- }
- }
- } else {
- result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
- }
- }
- }
- return !!result;
- }
+ var reduceRight = createReduce(arrayReduceRight, baseEachRight);
/**
- * A specialized version of `baseIsEqualDeep` for comparing objects of
- * the same `toStringTag`.
+ * The opposite of `_.filter`; this method returns the elements of `collection`
+ * that `predicate` does **not** return truthy for.
*
- * **Note:** This function only supports comparing values with tags of
- * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the new filtered array.
+ * @example
*
- * @private
- * @param {Object} value The object to compare.
- * @param {Object} other The other object to compare.
- * @param {string} tag The `toStringTag` of the objects to compare.
- * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ * _.reject([1, 2, 3, 4], function(n) {
+ * return n % 2 == 0;
+ * });
+ * // => [1, 3]
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user');
+ * // => ['barney']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.reject(users, 'active', false), 'user');
+ * // => ['fred']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.reject(users, 'active'), 'user');
+ * // => ['barney']
*/
- function equalByTag(object, other, tag) {
- switch (tag) {
- case boolTag:
- case dateTag:
- // Coerce dates and booleans to numbers, dates to milliseconds and booleans
- // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
- return +object == +other;
-
- case errorTag:
- return object.name == other.name && object.message == other.message;
-
- case numberTag:
- // Treat `NaN` vs. `NaN` as equal.
- return (object != +object)
- ? other != +other
- // But, treat `-0` vs. `+0` as not equal.
- : (object == 0 ? ((1 / object) == (1 / other)) : object == +other);
-
- case regexpTag:
- case stringTag:
- // Coerce regexes to strings and treat strings primitives and string
- // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
- return object == (other + '');
- }
- return false;
+ function reject(collection, predicate, thisArg) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ predicate = getCallback(predicate, thisArg, 3);
+ return func(collection, function(value, index, collection) {
+ return !predicate(value, index, collection);
+ });
}
/**
- * A specialized version of `baseIsEqualDeep` for objects with support for
- * partial deep comparisons.
+ * Gets a random element or `n` random elements from a collection.
*
- * @private
- * @param {Object} object The object to compare.
- * @param {Object} other The other object to compare.
- * @param {Function} equalFunc The function to determine equivalents of values.
- * @param {Function} [customizer] The function to customize comparing values.
- * @param {boolean} [isLoose] Specify performing partial comparisons.
- * @param {Array} [stackA] Tracks traversed `value` objects.
- * @param {Array} [stackB] Tracks traversed `other` objects.
- * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to sample.
+ * @param {number} [n] The number of elements to sample.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {*} Returns the random sample(s).
+ * @example
+ *
+ * _.sample([1, 2, 3, 4]);
+ * // => 2
+ *
+ * _.sample([1, 2, 3, 4], 2);
+ * // => [3, 1]
*/
- function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
- var objProps = keys(object),
- objLength = objProps.length,
- othProps = keys(other),
- othLength = othProps.length;
-
- if (objLength != othLength && !isLoose) {
- return false;
- }
- var skipCtor = isLoose,
- index = -1;
-
- while (++index < objLength) {
- var key = objProps[index],
- result = isLoose ? key in other : hasOwnProperty.call(other, key);
-
- if (result) {
- var objValue = object[key],
- othValue = other[key];
-
- result = undefined;
- if (customizer) {
- result = isLoose
- ? customizer(othValue, objValue, key)
- : customizer(objValue, othValue, key);
- }
- if (result === undefined) {
- // Recursively compare objects (susceptible to call stack limits).
- result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB);
- }
- }
- if (!result) {
- return false;
- }
- skipCtor || (skipCtor = key == 'constructor');
- }
- if (!skipCtor) {
- var objCtor = object.constructor,
- othCtor = other.constructor;
-
- // Non `Object` object instances with different constructors are not equal.
- if (objCtor != othCtor &&
- ('constructor' in object && 'constructor' in other) &&
- !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
- typeof othCtor == 'function' && othCtor instanceof othCtor)) {
- return false;
- }
+ function sample(collection, n, guard) {
+ if (guard ? isIterateeCall(collection, n, guard) : n == null) {
+ collection = toIterable(collection);
+ var length = collection.length;
+ return length > 0 ? collection[baseRandom(0, length - 1)] : undefined;
}
- return true;
+ var result = shuffle(collection);
+ result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length);
+ return result;
}
/**
- * Gets the extremum value of `collection` invoking `iteratee` for each value
- * in `collection` to generate the criterion by which the value is ranked.
- * The `iteratee` is invoked with three arguments: (value, index, collection).
+ * Creates an array of shuffled values, using a version of the
+ * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
*
- * @private
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @param {boolean} [isMin] Specify returning the minimum, instead of the
- * maximum, extremum value.
- * @returns {*} Returns the extremum value.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ * @example
+ *
+ * _.shuffle([1, 2, 3, 4]);
+ * // => [4, 1, 3, 2]
*/
- function extremumBy(collection, iteratee, isMin) {
- var exValue = isMin ? POSITIVE_INFINITY : NEGATIVE_INFINITY,
- computed = exValue,
- result = computed;
+ function shuffle(collection) {
+ collection = toIterable(collection);
- baseEach(collection, function(value, index, collection) {
- var current = iteratee(value, index, collection);
- if ((isMin ? (current < computed) : (current > computed)) ||
- (current === exValue && current === result)) {
- computed = current;
- result = value;
+ var index = -1,
+ length = collection.length,
+ result = Array(length);
+
+ while (++index < length) {
+ var rand = baseRandom(0, index);
+ if (index != rand) {
+ result[index] = result[rand];
}
- });
+ result[rand] = collection[index];
+ }
return result;
}
/**
- * Gets the appropriate "callback" function. If the `_.callback` method is
- * customized this function returns the custom method, otherwise it returns
- * the `baseCallback` function. If arguments are provided the chosen function
- * is invoked with them and its result is returned.
+ * Gets the size of `collection` by returning its length for array-like
+ * values or the number of own enumerable properties for objects.
*
- * @private
- * @returns {Function} Returns the chosen function or its result.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to inspect.
+ * @returns {number} Returns the size of `collection`.
+ * @example
+ *
+ * _.size([1, 2, 3]);
+ * // => 3
+ *
+ * _.size({ 'a': 1, 'b': 2 });
+ * // => 2
+ *
+ * _.size('pebbles');
+ * // => 7
*/
- function getCallback(func, thisArg, argCount) {
- var result = lodash.callback || callback;
- result = result === callback ? baseCallback : result;
- return argCount ? result(func, thisArg, argCount) : result;
+ function size(collection) {
+ var length = collection ? getLength(collection) : 0;
+ return isLength(length) ? length : keys(collection).length;
}
/**
- * Gets metadata for `func`.
+ * Checks if `predicate` returns truthy for **any** element of `collection`.
+ * The function returns as soon as it finds a passing value and does not iterate
+ * over the entire collection. The predicate is bound to `thisArg` and invoked
+ * with three arguments: (value, index|key, collection).
*
- * @private
- * @param {Function} func The function to query.
- * @returns {*} Returns the metadata for `func`.
- */
- var getData = !metaMap ? noop : function(func) {
- return metaMap.get(func);
- };
-
- /**
- * Gets the name of `func`.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
*
- * @private
- * @param {Function} func The function to query.
- * @returns {string} Returns the function name.
- */
- var getFuncName = (function() {
- if (!support.funcNames) {
- return constant('');
- }
- if (constant.name == 'constant') {
- return baseProperty('name');
- }
- return function(func) {
- var result = func.name,
- array = realNames[result],
- length = array ? array.length : 0;
-
- while (length--) {
- var data = array[length],
- otherFunc = data.func;
-
- if (otherFunc == null || otherFunc == func) {
- return data.name;
- }
- }
- return result;
- };
- }());
-
- /**
- * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
- * customized this function returns the custom method, otherwise it returns
- * the `baseIndexOf` function. If arguments are provided the chosen function
- * is invoked with them and its result is returned.
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
*
- * @private
- * @returns {Function|number} Returns the chosen function or its result.
- */
- function getIndexOf(collection, target, fromIndex) {
- var result = lodash.indexOf || indexOf;
- result = result === indexOf ? baseIndexOf : result;
- return collection ? result(collection, target, fromIndex) : result;
- }
-
- /**
- * Gets the "length" property value of `object`.
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
*
- * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
- * in Safari on iOS 8.1 ARM64.
+ * @static
+ * @memberOf _
+ * @alias any
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ * @example
*
- * @private
- * @param {Object} object The object to query.
- * @returns {*} Returns the "length" value.
- */
- var getLength = baseProperty('length');
-
- /**
- * Creates an array of the own symbols of `object`.
+ * _.some([null, 0, 'yes', false], Boolean);
+ * // => true
*
- * @private
- * @param {Object} object The object to query.
- * @returns {Array} Returns the array of symbols.
- */
- var getSymbols = !getOwnPropertySymbols ? constant([]) : function(object) {
- return getOwnPropertySymbols(toObject(object));
- };
-
- /**
- * Gets the view, applying any `transforms` to the `start` and `end` positions.
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false }
+ * ];
*
- * @private
- * @param {number} start The start of the view.
- * @param {number} end The end of the view.
- * @param {Array} [transforms] The transformations to apply to the view.
- * @returns {Object} Returns an object containing the `start` and `end`
- * positions of the view.
+ * // using the `_.matches` callback shorthand
+ * _.some(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.some(users, 'active', false);
+ * // => true
+ *
+ * // using the `_.property` callback shorthand
+ * _.some(users, 'active');
+ * // => true
*/
- function getView(start, end, transforms) {
- var index = -1,
- length = transforms ? transforms.length : 0;
-
- while (++index < length) {
- var data = transforms[index],
- size = data.size;
-
- switch (data.type) {
- case 'drop': start += size; break;
- case 'dropRight': end -= size; break;
- case 'take': end = nativeMin(end, start + size); break;
- case 'takeRight': start = nativeMax(start, end - size); break;
- }
+ function some(collection, predicate, thisArg) {
+ var func = isArray(collection) ? arraySome : baseSome;
+ if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
+ predicate = null;
}
- return { 'start': start, 'end': end };
+ if (typeof predicate != 'function' || thisArg !== undefined) {
+ predicate = getCallback(predicate, thisArg, 3);
+ }
+ return func(collection, predicate);
}
/**
- * Initializes an array clone.
+ * Creates an array of elements, sorted in ascending order by the results of
+ * running each element in a collection through `iteratee`. This method performs
+ * a stable sort, that is, it preserves the original sort order of equal elements.
+ * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
*
- * @private
- * @param {Array} array The array to clone.
- * @returns {Array} Returns the initialized clone.
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * _.sortBy([1, 2, 3], function(n) {
+ * return Math.sin(n);
+ * });
+ * // => [3, 1, 2]
+ *
+ * _.sortBy([1, 2, 3], function(n) {
+ * return this.sin(n);
+ * }, Math);
+ * // => [3, 1, 2]
+ *
+ * var users = [
+ * { 'user': 'fred' },
+ * { 'user': 'pebbles' },
+ * { 'user': 'barney' }
+ * ];
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.sortBy(users, 'user'), 'user');
+ * // => ['barney', 'fred', 'pebbles']
*/
- function initCloneArray(array) {
- var length = array.length,
- result = new array.constructor(length);
-
- // Add array properties assigned by `RegExp#exec`.
- if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
- result.index = array.index;
- result.input = array.input;
+ function sortBy(collection, iteratee, thisArg) {
+ if (collection == null) {
+ return [];
}
- return result;
+ if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
+ iteratee = null;
+ }
+ var index = -1;
+ iteratee = getCallback(iteratee, thisArg, 3);
+
+ var result = baseMap(collection, function(value, key, collection) {
+ return { 'criteria': iteratee(value, key, collection), 'index': ++index, 'value': value };
+ });
+ return baseSortBy(result, compareAscending);
}
/**
- * Initializes an object clone.
+ * This method is like `_.sortBy` except that it can sort by multiple iteratees
+ * or property names.
*
- * @private
- * @param {Object} object The object to clone.
- * @returns {Object} Returns the initialized clone.
+ * If a property name is provided for an iteratee the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If an object is provided for an iteratee the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {...(Function|Function[]|Object|Object[]|string|string[])} iteratees
+ * The iteratees to sort by, specified as individual values or arrays of values.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 42 },
+ * { 'user': 'barney', 'age': 34 }
+ * ];
+ *
+ * _.map(_.sortByAll(users, ['user', 'age']), _.values);
+ * // => [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]
+ *
+ * _.map(_.sortByAll(users, 'user', function(chr) {
+ * return Math.floor(chr.age / 10);
+ * }), _.values);
+ * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
*/
- function initCloneObject(object) {
- var Ctor = object.constructor;
- if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
- Ctor = Object;
+ var sortByAll = restParam(function(collection, iteratees) {
+ if (collection == null) {
+ return [];
}
- return new Ctor;
- }
+ var guard = iteratees[2];
+ if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) {
+ iteratees.length = 1;
+ }
+ return baseSortByOrder(collection, baseFlatten(iteratees), []);
+ });
/**
- * Initializes an object clone based on its `toStringTag`.
+ * This method is like `_.sortByAll` except that it allows specifying the
+ * sort orders of the iteratees to sort by. A truthy value in `orders` will
+ * sort the corresponding property name in ascending order while a falsey
+ * value will sort it in descending order.
*
- * **Note:** This function only supports cloning values with tags of
- * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ * If a property name is provided for an iteratee the created `_.property`
+ * style callback returns the property value of the given element.
*
- * @private
- * @param {Object} object The object to clone.
- * @param {string} tag The `toStringTag` of the object to clone.
- * @param {boolean} [isDeep] Specify a deep clone.
- * @returns {Object} Returns the initialized clone.
- */
- function initCloneByTag(object, tag, isDeep) {
- var Ctor = object.constructor;
- switch (tag) {
- case arrayBufferTag:
- return bufferClone(object);
-
- case boolTag:
- case dateTag:
- return new Ctor(+object);
-
- case float32Tag: case float64Tag:
- case int8Tag: case int16Tag: case int32Tag:
- case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
- var buffer = object.buffer;
- return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
-
- case numberTag:
- case stringTag:
- return new Ctor(object);
-
- case regexpTag:
- var result = new Ctor(object.source, reFlags.exec(object));
- result.lastIndex = object.lastIndex;
- }
- return result;
- }
-
- /**
- * Invokes the method at `path` on `object`.
+ * If an object is provided for an iteratee the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
*
- * @private
- * @param {Object} object The object to query.
- * @param {Array|string} path The path of the method to invoke.
- * @param {Array} args The arguments to invoke the method with.
- * @returns {*} Returns the result of the invoked method.
- */
- function invokePath(object, path, args) {
- if (object != null && !isKey(path, object)) {
- path = toPath(path);
- object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
- path = last(path);
- }
- var func = object == null ? object : object[path];
- return func == null ? undefined : func.apply(object, args);
- }
-
- /**
- * Checks if `value` is a valid array-like index.
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+ * @param {boolean[]} orders The sort orders of `iteratees`.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
+ * @returns {Array} Returns the new sorted array.
+ * @example
*
- * @private
- * @param {*} value The value to check.
- * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
- * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
- */
- function isIndex(value, length) {
- value = +value;
- length = length == null ? MAX_SAFE_INTEGER : length;
- return value > -1 && value % 1 == 0 && value < length;
- }
-
- /**
- * Checks if the provided arguments are from an iteratee call.
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 34 },
+ * { 'user': 'fred', 'age': 42 },
+ * { 'user': 'barney', 'age': 36 }
+ * ];
*
- * @private
- * @param {*} value The potential iteratee value argument.
- * @param {*} index The potential iteratee index or key argument.
- * @param {*} object The potential iteratee object argument.
- * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
+ * // sort by `user` in ascending order and by `age` in descending order
+ * _.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values);
+ * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
*/
- function isIterateeCall(value, index, object) {
- if (!isObject(object)) {
- return false;
+ function sortByOrder(collection, iteratees, orders, guard) {
+ if (collection == null) {
+ return [];
}
- var type = typeof index;
- if (type == 'number') {
- var length = getLength(object),
- prereq = isLength(length) && isIndex(index, length);
- } else {
- prereq = type == 'string' && index in object;
+ if (guard && isIterateeCall(iteratees, orders, guard)) {
+ orders = null;
}
- if (prereq) {
- var other = object[index];
- return value === value ? (value === other) : (other !== other);
+ if (!isArray(iteratees)) {
+ iteratees = iteratees == null ? [] : [iteratees];
}
- return false;
+ if (!isArray(orders)) {
+ orders = orders == null ? [] : [orders];
+ }
+ return baseSortByOrder(collection, iteratees, orders);
}
/**
- * Checks if `value` is a property name and not a property path.
+ * Performs a deep comparison between each element in `collection` and the
+ * source object, returning an array of all elements that have equivalent
+ * property values.
*
- * @private
- * @param {*} value The value to check.
- * @param {Object} [object] The object to query keys on.
- * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
+ * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+ * numbers, `Object` objects, regexes, and strings. Objects are compared by
+ * their own, not inherited, enumerable properties. For comparing a single
+ * own or inherited property value see `_.matchesProperty`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Object} source The object of property values to match.
+ * @returns {Array} Returns the new filtered array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false, 'pets': ['hoppy'] },
+ * { 'user': 'fred', 'age': 40, 'active': true, 'pets': ['baby puss', 'dino'] }
+ * ];
+ *
+ * _.pluck(_.where(users, { 'age': 36, 'active': false }), 'user');
+ * // => ['barney']
+ *
+ * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user');
+ * // => ['fred']
*/
- function isKey(value, object) {
- var type = typeof value;
- if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
- return true;
- }
- if (isArray(value)) {
- return false;
- }
- var result = !reIsDeepProp.test(value);
- return result || (object != null && value in toObject(object));
+ function where(collection, source) {
+ return filter(collection, baseMatches(source));
}
/**
- * Checks if `func` has a lazy counterpart.
+ * Gets the number of milliseconds that have elapsed since the Unix epoch
+ * (1 January 1970 00:00:00 UTC).
*
- * @private
- * @param {Function} func The function to check.
- * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.
+ * @static
+ * @memberOf _
+ * @category Date
+ * @example
+ *
+ * _.defer(function(stamp) {
+ * console.log(_.now() - stamp);
+ * }, _.now());
+ * // => logs the number of milliseconds it took for the deferred function to be invoked
*/
- function isLaziable(func) {
- var funcName = getFuncName(func);
- return !!funcName && func === lodash[funcName] && funcName in LazyWrapper.prototype;
- }
+ var now = nativeNow || function() {
+ return new Date().getTime();
+ };
/**
- * Checks if `value` is a valid array-like length.
+ * The opposite of `_.before`; this method creates a function that invokes
+ * `func` once it is called `n` or more times.
*
- * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {number} n The number of calls before `func` is invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
*
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ * var saves = ['profile', 'settings'];
+ *
+ * var done = _.after(saves.length, function() {
+ * console.log('done saving!');
+ * });
+ *
+ * _.forEach(saves, function(type) {
+ * asyncSave({ 'type': type, 'complete': done });
+ * });
+ * // => logs 'done saving!' after the two async saves have completed
*/
- function isLength(value) {
- return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+ function after(n, func) {
+ if (typeof func != 'function') {
+ if (typeof n == 'function') {
+ var temp = n;
+ n = func;
+ func = temp;
+ } else {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ }
+ n = nativeIsFinite(n = +n) ? n : 0;
+ return function() {
+ if (--n < 1) {
+ return func.apply(this, arguments);
+ }
+ };
}
/**
- * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
+ * Creates a function that accepts up to `n` arguments ignoring any
+ * additional arguments.
*
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` if suitable for strict
- * equality comparisons, else `false`.
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to cap arguments for.
+ * @param {number} [n=func.length] The arity cap.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * _.map(['6', '8', '10'], _.ary(parseInt, 1));
+ * // => [6, 8, 10]
*/
- function isStrictComparable(value) {
- return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value));
+ function ary(func, n, guard) {
+ if (guard && isIterateeCall(func, n, guard)) {
+ n = null;
+ }
+ n = (func && n == null) ? func.length : nativeMax(+n || 0, 0);
+ return createWrapper(func, ARY_FLAG, null, null, null, null, n);
}
/**
- * Merges the function metadata of `source` into `data`.
+ * Creates a function that invokes `func`, with the `this` binding and arguments
+ * of the created function, while it is called less than `n` times. Subsequent
+ * calls to the created function return the result of the last `func` invocation.
*
- * Merging metadata reduces the number of wrappers required to invoke a function.
- * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
- * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`
- * augment function arguments, making the order in which they are executed important,
- * preventing the merging of metadata. However, we make an exception for a safe
- * common case where curried functions have `_.ary` and or `_.rearg` applied.
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {number} n The number of calls at which `func` is no longer invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
*
- * @private
- * @param {Array} data The destination metadata.
- * @param {Array} source The source metadata.
- * @returns {Array} Returns `data`.
+ * jQuery('#add').on('click', _.before(5, addContactToList));
+ * // => allows adding up to 4 contacts to the list
*/
- function mergeData(data, source) {
- var bitmask = data[1],
- srcBitmask = source[1],
- newBitmask = bitmask | srcBitmask,
- isCommon = newBitmask < ARY_FLAG;
-
- var isCombo =
- (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) ||
- (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) ||
- (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);
-
- // Exit early if metadata can't be merged.
- if (!(isCommon || isCombo)) {
- return data;
- }
- // Use source `thisArg` if available.
- if (srcBitmask & BIND_FLAG) {
- data[2] = source[2];
- // Set when currying a bound function.
- newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
- }
- // Compose partial arguments.
- var value = source[3];
- if (value) {
- var partials = data[3];
- data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
- data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
- }
- // Compose partial right arguments.
- value = source[5];
- if (value) {
- partials = data[5];
- data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
- data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
- }
- // Use source `argPos` if available.
- value = source[7];
- if (value) {
- data[7] = arrayCopy(value);
- }
- // Use source `ary` if it's smaller.
- if (srcBitmask & ARY_FLAG) {
- data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
- }
- // Use source `arity` if one is not provided.
- if (data[9] == null) {
- data[9] = source[9];
+ function before(n, func) {
+ var result;
+ if (typeof func != 'function') {
+ if (typeof n == 'function') {
+ var temp = n;
+ n = func;
+ func = temp;
+ } else {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
}
- // Use source `func` and merge bitmasks.
- data[0] = source[0];
- data[1] = newBitmask;
-
- return data;
+ return function() {
+ if (--n > 0) {
+ result = func.apply(this, arguments);
+ }
+ if (n <= 1) {
+ func = null;
+ }
+ return result;
+ };
}
/**
- * A specialized version of `_.pick` that picks `object` properties specified
- * by `props`.
+ * Creates a function that invokes `func` with the `this` binding of `thisArg`
+ * and prepends any additional `_.bind` arguments to those provided to the
+ * bound function.
*
- * @private
- * @param {Object} object The source object.
- * @param {string[]} props The property names to pick.
- * @returns {Object} Returns the new object.
+ * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** Unlike native `Function#bind` this method does not set the "length"
+ * property of bound functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var greet = function(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * };
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * var bound = _.bind(greet, object, 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * // using placeholders
+ * var bound = _.bind(greet, object, _, '!');
+ * bound('hi');
+ * // => 'hi fred!'
*/
- function pickByArray(object, props) {
- object = toObject(object);
-
- var index = -1,
- length = props.length,
- result = {};
-
- while (++index < length) {
- var key = props[index];
- if (key in object) {
- result[key] = object[key];
- }
+ var bind = restParam(function(func, thisArg, partials) {
+ var bitmask = BIND_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, bind.placeholder);
+ bitmask |= PARTIAL_FLAG;
}
- return result;
- }
+ return createWrapper(func, bitmask, thisArg, partials, holders);
+ });
/**
- * A specialized version of `_.pick` that picks `object` properties `predicate`
- * returns truthy for.
+ * Binds methods of an object to the object itself, overwriting the existing
+ * method. Method names may be specified as individual arguments or as arrays
+ * of method names. If no method names are provided all enumerable function
+ * properties, own and inherited, of `object` are bound.
*
- * @private
- * @param {Object} object The source object.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {Object} Returns the new object.
- */
- function pickByCallback(object, predicate) {
- var result = {};
- baseForIn(object, function(value, key, object) {
- if (predicate(value, key, object)) {
- result[key] = value;
- }
- });
- return result;
- }
-
- /**
- * Reorder `array` according to the specified indexes where the element at
- * the first index is assigned as the first element, the element at
- * the second index is assigned as the second element, and so on.
+ * **Note:** This method does not set the "length" property of bound functions.
*
- * @private
- * @param {Array} array The array to reorder.
- * @param {Array} indexes The arranged array indexes.
- * @returns {Array} Returns `array`.
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Object} object The object to bind and assign the bound methods to.
+ * @param {...(string|string[])} [methodNames] The object method names to bind,
+ * specified as individual method names or arrays of method names.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var view = {
+ * 'label': 'docs',
+ * 'onClick': function() {
+ * console.log('clicked ' + this.label);
+ * }
+ * };
+ *
+ * _.bindAll(view);
+ * jQuery('#docs').on('click', view.onClick);
+ * // => logs 'clicked docs' when the element is clicked
*/
- function reorder(array, indexes) {
- var arrLength = array.length,
- length = nativeMin(indexes.length, arrLength),
- oldArray = arrayCopy(array);
+ var bindAll = restParam(function(object, methodNames) {
+ methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object);
- while (length--) {
- var index = indexes[length];
- array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
+ var index = -1,
+ length = methodNames.length;
+
+ while (++index < length) {
+ var key = methodNames[index];
+ object[key] = createWrapper(object[key], BIND_FLAG, object);
}
- return array;
- }
+ return object;
+ });
/**
- * Sets metadata for `func`.
+ * Creates a function that invokes the method at `object[key]` and prepends
+ * any additional `_.bindKey` arguments to those provided to the bound function.
*
- * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
- * period of time, it will trip its breaker and transition to an identity function
- * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)
+ * This method differs from `_.bind` by allowing bound functions to reference
+ * methods that may be redefined or don't yet exist.
+ * See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
* for more details.
*
- * @private
- * @param {Function} func The function to associate metadata with.
- * @param {*} data The metadata.
- * @returns {Function} Returns `func`.
- */
- var setData = (function() {
- var count = 0,
- lastCalled = 0;
-
- return function(key, value) {
- var stamp = now(),
- remaining = HOT_SPAN - (stamp - lastCalled);
-
- lastCalled = stamp;
- if (remaining > 0) {
- if (++count >= HOT_COUNT) {
- return key;
- }
- } else {
- count = 0;
- }
- return baseSetData(key, value);
- };
- }());
-
- /**
- * A fallback implementation of `_.isPlainObject` which checks if `value`
- * is an object created by the `Object` constructor or has a `[[Prototype]]`
- * of `null`.
+ * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
*
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
- */
- function shimIsPlainObject(value) {
- var Ctor,
- support = lodash.support;
-
- // Exit early for non `Object` objects.
- if (!(isObjectLike(value) && objToString.call(value) == objectTag) ||
- (!hasOwnProperty.call(value, 'constructor') &&
- (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
- return false;
- }
- // IE < 9 iterates inherited properties before own properties. If the first
- // iterated property is an object's own property then there are no inherited
- // enumerable properties.
- var result;
- // In most environments an object's own properties are iterated before
- // its inherited properties. If the last iterated property is an object's
- // own property then there are no inherited enumerable properties.
- baseForIn(value, function(subValue, key) {
- result = key;
- });
- return result === undefined || hasOwnProperty.call(value, result);
- }
-
- /**
- * A fallback implementation of `Object.keys` which creates an array of the
- * own enumerable property names of `object`.
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Object} object The object the method belongs to.
+ * @param {string} key The key of the method.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
*
- * @private
- * @param {Object} object The object to query.
- * @returns {Array} Returns the array of property names.
- */
- function shimKeys(object) {
- var props = keysIn(object),
- propsLength = props.length,
- length = propsLength && object.length,
- support = lodash.support;
-
- var allowIndexes = length && isLength(length) &&
- (isArray(object) || (support.nonEnumArgs && isArguments(object)));
-
- var index = -1,
- result = [];
-
- while (++index < propsLength) {
- var key = props[index];
- if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
- result.push(key);
- }
- }
- return result;
- }
-
- /**
- * Converts `value` to an array-like object if it is not one.
+ * var object = {
+ * 'user': 'fred',
+ * 'greet': function(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * }
+ * };
*
- * @private
- * @param {*} value The value to process.
- * @returns {Array|Object} Returns the array-like object.
- */
- function toIterable(value) {
- if (value == null) {
- return [];
- }
- if (!isLength(getLength(value))) {
- return values(value);
- }
- return isObject(value) ? value : Object(value);
- }
-
- /**
- * Converts `value` to an object if it is not one.
+ * var bound = _.bindKey(object, 'greet', 'hi');
+ * bound('!');
+ * // => 'hi fred!'
*
- * @private
- * @param {*} value The value to process.
- * @returns {Object} Returns the object.
- */
- function toObject(value) {
- return isObject(value) ? value : Object(value);
- }
-
- /**
- * Converts `value` to property path array if it is not one.
+ * object.greet = function(greeting, punctuation) {
+ * return greeting + 'ya ' + this.user + punctuation;
+ * };
*
- * @private
- * @param {*} value The value to process.
- * @returns {Array} Returns the property path array.
+ * bound('!');
+ * // => 'hiya fred!'
+ *
+ * // using placeholders
+ * var bound = _.bindKey(object, 'greet', _, '!');
+ * bound('hi');
+ * // => 'hiya fred!'
*/
- function toPath(value) {
- if (isArray(value)) {
- return value;
+ var bindKey = restParam(function(object, key, partials) {
+ var bitmask = BIND_FLAG | BIND_KEY_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, bindKey.placeholder);
+ bitmask |= PARTIAL_FLAG;
}
- var result = [];
- baseToString(value).replace(rePropName, function(match, number, quote, string) {
- result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
- });
- return result;
- }
+ return createWrapper(key, bitmask, object, partials, holders);
+ });
/**
- * Creates a clone of `wrapper`.
+ * Creates a function that accepts one or more arguments of `func` that when
+ * called either invokes `func` returning its result, if all `func` arguments
+ * have been provided, or returns a function that accepts one or more of the
+ * remaining `func` arguments, and so on. The arity of `func` may be specified
+ * if `func.length` is not sufficient.
*
- * @private
- * @param {Object} wrapper The wrapper to clone.
- * @returns {Object} Returns the cloned wrapper.
- */
- function wrapperClone(wrapper) {
- return wrapper instanceof LazyWrapper
- ? wrapper.clone()
- : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));
- }
-
- /*------------------------------------------------------------------------*/
-
- /**
- * Creates an array of elements split into groups the length of `size`.
- * If `collection` can't be split evenly, the final chunk will be the remaining
- * elements.
+ * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method does not set the "length" property of curried functions.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to process.
- * @param {number} [size=1] The length of each chunk.
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Array} Returns the new array containing chunks.
+ * @returns {Function} Returns the new curried function.
* @example
*
- * _.chunk(['a', 'b', 'c', 'd'], 2);
- * // => [['a', 'b'], ['c', 'd']]
- *
- * _.chunk(['a', 'b', 'c', 'd'], 3);
- * // => [['a', 'b', 'c'], ['d']]
- */
- function chunk(array, size, guard) {
- if (guard ? isIterateeCall(array, size, guard) : size == null) {
- size = 1;
- } else {
- size = nativeMax(+size || 1, 1);
- }
- var index = 0,
- length = array ? array.length : 0,
- resIndex = -1,
- result = Array(ceil(length / size));
-
- while (index < length) {
- result[++resIndex] = baseSlice(array, index, (index += size));
- }
- return result;
- }
-
- /**
- * Creates an array with all falsey values removed. The values `false`, `null`,
- * `0`, `""`, `undefined`, and `NaN` are falsey.
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
*
- * @static
- * @memberOf _
- * @category Array
- * @param {Array} array The array to compact.
- * @returns {Array} Returns the new array of filtered values.
- * @example
+ * var curried = _.curry(abc);
*
- * _.compact([0, 1, false, 2, '', 3]);
+ * curried(1)(2)(3);
* // => [1, 2, 3]
- */
- function compact(array) {
- var index = -1,
- length = array ? array.length : 0,
- resIndex = -1,
- result = [];
-
- while (++index < length) {
- var value = array[index];
- if (value) {
- result[++resIndex] = value;
- }
- }
- return result;
- }
-
- /**
- * Creates an array excluding all values of the provided arrays using
- * `SameValueZero` for equality comparisons.
*
- * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
- * comparisons are like strict equality comparisons, e.g. `===`, except that
- * `NaN` matches `NaN`.
+ * curried(1, 2)(3);
+ * // => [1, 2, 3]
*
- * @static
- * @memberOf _
- * @category Array
- * @param {Array} array The array to inspect.
- * @param {...Array} [values] The arrays of values to exclude.
- * @returns {Array} Returns the new array of filtered values.
- * @example
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
*
- * _.difference([1, 2, 3], [4, 2]);
- * // => [1, 3]
+ * // using placeholders
+ * curried(1)(_, 3)(2);
+ * // => [1, 2, 3]
*/
- var difference = restParam(function(array, values) {
- return (isArray(array) || isArguments(array))
- ? baseDifference(array, baseFlatten(values, false, true))
- : [];
- });
+ var curry = createCurry(CURRY_FLAG);
/**
- * Creates a slice of `array` with `n` elements dropped from the beginning.
+ * This method is like `_.curry` except that arguments are applied to `func`
+ * in the manner of `_.partialRight` instead of `_.partial`.
+ *
+ * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method does not set the "length" property of curried functions.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @param {number} [n=1] The number of elements to drop.
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Array} Returns the slice of `array`.
+ * @returns {Function} Returns the new curried function.
* @example
*
- * _.drop([1, 2, 3]);
- * // => [2, 3]
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
*
- * _.drop([1, 2, 3], 2);
- * // => [3]
+ * var curried = _.curryRight(abc);
*
- * _.drop([1, 2, 3], 5);
- * // => []
- *
- * _.drop([1, 2, 3], 0);
+ * curried(3)(2)(1);
* // => [1, 2, 3]
- */
- function drop(array, n, guard) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
- if (guard ? isIterateeCall(array, n, guard) : n == null) {
- n = 1;
- }
- return baseSlice(array, n < 0 ? 0 : n);
- }
-
- /**
- * Creates a slice of `array` with `n` elements dropped from the end.
- *
- * @static
- * @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @param {number} [n=1] The number of elements to drop.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Array} Returns the slice of `array`.
- * @example
*
- * _.dropRight([1, 2, 3]);
- * // => [1, 2]
- *
- * _.dropRight([1, 2, 3], 2);
- * // => [1]
+ * curried(2, 3)(1);
+ * // => [1, 2, 3]
*
- * _.dropRight([1, 2, 3], 5);
- * // => []
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
*
- * _.dropRight([1, 2, 3], 0);
+ * // using placeholders
+ * curried(3)(1, _)(2);
* // => [1, 2, 3]
*/
- function dropRight(array, n, guard) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
- if (guard ? isIterateeCall(array, n, guard) : n == null) {
- n = 1;
- }
- n = length - (+n || 0);
- return baseSlice(array, 0, n < 0 ? 0 : n);
- }
+ var curryRight = createCurry(CURRY_RIGHT_FLAG);
/**
- * Creates a slice of `array` excluding elements dropped from the end.
- * Elements are dropped until `predicate` returns falsey. The predicate is
- * bound to `thisArg` and invoked with three arguments: (value, index, array).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
+ * Creates a function that delays invoking `func` until after `wait` milliseconds
+ * have elapsed since the last time it was invoked. The created function comes
+ * with a `cancel` method to cancel delayed invocations. Provide an options
+ * object to indicate that `func` should be invoked on the leading and/or
+ * trailing edge of the `wait` timeout. Subsequent calls to the debounced
+ * function return the result of the last `func` invocation.
*
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
+ * on the trailing edge of the timeout only if the the debounced function is
+ * invoked more than once during the `wait` timeout.
*
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that match the properties of the given
- * object, else `false`.
+ * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
+ * for details over the differences between `_.debounce` and `_.throttle`.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the slice of `array`.
+ * @category Function
+ * @param {Function} func The function to debounce.
+ * @param {number} [wait=0] The number of milliseconds to delay.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.leading=false] Specify invoking on the leading
+ * edge of the timeout.
+ * @param {number} [options.maxWait] The maximum time `func` is allowed to be
+ * delayed before it is invoked.
+ * @param {boolean} [options.trailing=true] Specify invoking on the trailing
+ * edge of the timeout.
+ * @returns {Function} Returns the new debounced function.
* @example
*
- * _.dropRightWhile([1, 2, 3], function(n) {
- * return n > 1;
- * });
- * // => [1]
- *
- * var users = [
- * { 'user': 'barney', 'active': true },
- * { 'user': 'fred', 'active': false },
- * { 'user': 'pebbles', 'active': false }
- * ];
- *
- * // using the `_.matches` callback shorthand
- * _.pluck(_.dropRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
- * // => ['barney', 'fred']
- *
- * // using the `_.matchesProperty` callback shorthand
- * _.pluck(_.dropRightWhile(users, 'active', false), 'user');
- * // => ['barney']
- *
- * // using the `_.property` callback shorthand
- * _.pluck(_.dropRightWhile(users, 'active'), 'user');
- * // => ['barney', 'fred', 'pebbles']
- */
- function dropRightWhile(array, predicate, thisArg) {
- return (array && array.length)
- ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true)
- : [];
- }
-
- /**
- * Creates a slice of `array` excluding elements dropped from the beginning.
- * Elements are dropped until `predicate` returns falsey. The predicate is
- * bound to `thisArg` and invoked with three arguments: (value, index, array).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * // avoid costly calculations while the window size is in flux
+ * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
*
- * @static
- * @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the slice of `array`.
- * @example
+ * // invoke `sendMail` when the click event is fired, debouncing subsequent calls
+ * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
+ * 'leading': true,
+ * 'trailing': false
+ * }));
*
- * _.dropWhile([1, 2, 3], function(n) {
- * return n < 3;
- * });
- * // => [3]
+ * // ensure `batchLog` is invoked once after 1 second of debounced calls
+ * var source = new EventSource('/stream');
+ * jQuery(source).on('message', _.debounce(batchLog, 250, {
+ * 'maxWait': 1000
+ * }));
*
- * var users = [
- * { 'user': 'barney', 'active': false },
- * { 'user': 'fred', 'active': false },
- * { 'user': 'pebbles', 'active': true }
- * ];
+ * // cancel a debounced call
+ * var todoChanges = _.debounce(batchLog, 1000);
+ * Object.observe(models.todo, todoChanges);
*
- * // using the `_.matches` callback shorthand
- * _.pluck(_.dropWhile(users, { 'user': 'barney', 'active': false }), 'user');
- * // => ['fred', 'pebbles']
+ * Object.observe(models, function(changes) {
+ * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
+ * todoChanges.cancel();
+ * }
+ * }, ['delete']);
*
- * // using the `_.matchesProperty` callback shorthand
- * _.pluck(_.dropWhile(users, 'active', false), 'user');
- * // => ['pebbles']
+ * // ...at some point `models.todo` is changed
+ * models.todo.completed = true;
*
- * // using the `_.property` callback shorthand
- * _.pluck(_.dropWhile(users, 'active'), 'user');
- * // => ['barney', 'fred', 'pebbles']
+ * // ...before 1 second has passed `models.todo` is deleted
+ * // which cancels the debounced `todoChanges` call
+ * delete models.todo;
*/
- function dropWhile(array, predicate, thisArg) {
- return (array && array.length)
- ? baseWhile(array, getCallback(predicate, thisArg, 3), true)
- : [];
- }
+ function debounce(func, wait, options) {
+ var args,
+ maxTimeoutId,
+ result,
+ stamp,
+ thisArg,
+ timeoutId,
+ trailingCall,
+ lastCalled = 0,
+ maxWait = false,
+ trailing = true;
- /**
- * Fills elements of `array` with `value` from `start` up to, but not
- * including, `end`.
- *
- * **Note:** This method mutates `array`.
- *
- * @static
- * @memberOf _
- * @category Array
- * @param {Array} array The array to fill.
- * @param {*} value The value to fill `array` with.
- * @param {number} [start=0] The start position.
- * @param {number} [end=array.length] The end position.
- * @returns {Array} Returns `array`.
- * @example
- *
- * var array = [1, 2, 3];
- *
- * _.fill(array, 'a');
- * console.log(array);
- * // => ['a', 'a', 'a']
- *
- * _.fill(Array(3), 2);
- * // => [2, 2, 2]
- *
- * _.fill([4, 6, 8], '*', 1, 2);
- * // => [4, '*', 8]
- */
- function fill(array, value, start, end) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
}
- if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
- start = 0;
- end = length;
+ wait = wait < 0 ? 0 : (+wait || 0);
+ if (options === true) {
+ var leading = true;
+ trailing = false;
+ } else if (isObject(options)) {
+ leading = options.leading;
+ maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);
+ trailing = 'trailing' in options ? options.trailing : trailing;
}
- return baseFill(array, value, start, end);
- }
- /**
- * This method is like `_.find` except that it returns the index of the first
- * element `predicate` returns truthy for instead of the element itself.
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ function cancel() {
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ if (maxTimeoutId) {
+ clearTimeout(maxTimeoutId);
+ }
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ }
+
+ function delayed() {
+ var remaining = wait - (now() - stamp);
+ if (remaining <= 0 || remaining > wait) {
+ if (maxTimeoutId) {
+ clearTimeout(maxTimeoutId);
+ }
+ var isCalled = trailingCall;
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (isCalled) {
+ lastCalled = now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ } else {
+ timeoutId = setTimeout(delayed, remaining);
+ }
+ }
+
+ function maxDelayed() {
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (trailing || (maxWait !== wait)) {
+ lastCalled = now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ }
+
+ function debounced() {
+ args = arguments;
+ stamp = now();
+ thisArg = this;
+ trailingCall = trailing && (timeoutId || !leading);
+
+ if (maxWait === false) {
+ var leadingCall = leading && !timeoutId;
+ } else {
+ if (!maxTimeoutId && !leading) {
+ lastCalled = stamp;
+ }
+ var remaining = maxWait - (stamp - lastCalled),
+ isCalled = remaining <= 0 || remaining > maxWait;
+
+ if (isCalled) {
+ if (maxTimeoutId) {
+ maxTimeoutId = clearTimeout(maxTimeoutId);
+ }
+ lastCalled = stamp;
+ result = func.apply(thisArg, args);
+ }
+ else if (!maxTimeoutId) {
+ maxTimeoutId = setTimeout(maxDelayed, remaining);
+ }
+ }
+ if (isCalled && timeoutId) {
+ timeoutId = clearTimeout(timeoutId);
+ }
+ else if (!timeoutId && wait !== maxWait) {
+ timeoutId = setTimeout(delayed, wait);
+ }
+ if (leadingCall) {
+ isCalled = true;
+ result = func.apply(thisArg, args);
+ }
+ if (isCalled && !timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ return result;
+ }
+ debounced.cancel = cancel;
+ return debounced;
+ }
+
+ /**
+ * Defers invoking the `func` until the current call stack has cleared. Any
+ * additional arguments are provided to `func` when it is invoked.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to search.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {number} Returns the index of the found element, else `-1`.
+ * @category Function
+ * @param {Function} func The function to defer.
+ * @param {...*} [args] The arguments to invoke the function with.
+ * @returns {number} Returns the timer id.
* @example
*
- * var users = [
- * { 'user': 'barney', 'active': false },
- * { 'user': 'fred', 'active': false },
- * { 'user': 'pebbles', 'active': true }
- * ];
- *
- * _.findIndex(users, function(chr) {
- * return chr.user == 'barney';
- * });
- * // => 0
- *
- * // using the `_.matches` callback shorthand
- * _.findIndex(users, { 'user': 'fred', 'active': false });
- * // => 1
- *
- * // using the `_.matchesProperty` callback shorthand
- * _.findIndex(users, 'active', false);
- * // => 0
- *
- * // using the `_.property` callback shorthand
- * _.findIndex(users, 'active');
- * // => 2
+ * _.defer(function(text) {
+ * console.log(text);
+ * }, 'deferred');
+ * // logs 'deferred' after one or more milliseconds
*/
- var findIndex = createFindIndex();
+ var defer = restParam(function(func, args) {
+ return baseDelay(func, 1, args);
+ });
/**
- * This method is like `_.findIndex` except that it iterates over elements
- * of `collection` from right to left.
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * Invokes `func` after `wait` milliseconds. Any additional arguments are
+ * provided to `func` when it is invoked.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to search.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {number} Returns the index of the found element, else `-1`.
+ * @category Function
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {...*} [args] The arguments to invoke the function with.
+ * @returns {number} Returns the timer id.
* @example
*
- * var users = [
- * { 'user': 'barney', 'active': true },
- * { 'user': 'fred', 'active': false },
- * { 'user': 'pebbles', 'active': false }
- * ];
- *
- * _.findLastIndex(users, function(chr) {
- * return chr.user == 'pebbles';
- * });
- * // => 2
- *
- * // using the `_.matches` callback shorthand
- * _.findLastIndex(users, { 'user': 'barney', 'active': true });
- * // => 0
- *
- * // using the `_.matchesProperty` callback shorthand
- * _.findLastIndex(users, 'active', false);
- * // => 2
- *
- * // using the `_.property` callback shorthand
- * _.findLastIndex(users, 'active');
- * // => 0
+ * _.delay(function(text) {
+ * console.log(text);
+ * }, 1000, 'later');
+ * // => logs 'later' after one second
*/
- var findLastIndex = createFindIndex(true);
+ var delay = restParam(function(func, wait, args) {
+ return baseDelay(func, wait, args);
+ });
/**
- * Gets the first element of `array`.
+ * Creates a function that returns the result of invoking the provided
+ * functions with the `this` binding of the created function, where each
+ * successive invocation is supplied the return value of the previous.
*
* @static
* @memberOf _
- * @alias head
- * @category Array
- * @param {Array} array The array to query.
- * @returns {*} Returns the first element of `array`.
+ * @category Function
+ * @param {...Function} [funcs] Functions to invoke.
+ * @returns {Function} Returns the new function.
* @example
*
- * _.first([1, 2, 3]);
- * // => 1
+ * function square(n) {
+ * return n * n;
+ * }
*
- * _.first([]);
- * // => undefined
+ * var addSquare = _.flow(_.add, square);
+ * addSquare(1, 2);
+ * // => 9
*/
- function first(array) {
- return array ? array[0] : undefined;
- }
+ var flow = createFlow();
/**
- * Flattens a nested array. If `isDeep` is `true` the array is recursively
- * flattened, otherwise it is only flattened a single level.
+ * This method is like `_.flow` except that it creates a function that
+ * invokes the provided functions from right to left.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to flatten.
- * @param {boolean} [isDeep] Specify a deep flatten.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Array} Returns the new flattened array.
+ * @alias backflow, compose
+ * @category Function
+ * @param {...Function} [funcs] Functions to invoke.
+ * @returns {Function} Returns the new function.
* @example
*
- * _.flatten([1, [2, 3, [4]]]);
- * // => [1, 2, 3, [4]]
+ * function square(n) {
+ * return n * n;
+ * }
*
- * // using `isDeep`
- * _.flatten([1, [2, 3, [4]]], true);
- * // => [1, 2, 3, 4]
+ * var addSquare = _.flowRight(square, _.add);
+ * addSquare(1, 2);
+ * // => 9
*/
- function flatten(array, isDeep, guard) {
- var length = array ? array.length : 0;
- if (guard && isIterateeCall(array, isDeep, guard)) {
- isDeep = false;
- }
- return length ? baseFlatten(array, isDeep) : [];
- }
+ var flowRight = createFlow(true);
/**
- * Recursively flattens a nested array.
+ * Creates a function that memoizes the result of `func`. If `resolver` is
+ * provided it determines the cache key for storing the result based on the
+ * arguments provided to the memoized function. By default, the first argument
+ * provided to the memoized function is coerced to a string and used as the
+ * cache key. The `func` is invoked with the `this` binding of the memoized
+ * function.
+ *
+ * **Note:** The cache is exposed as the `cache` property on the memoized
+ * function. Its creation may be customized by replacing the `_.memoize.Cache`
+ * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object)
+ * method interface of `get`, `has`, and `set`.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to recursively flatten.
- * @returns {Array} Returns the new flattened array.
+ * @category Function
+ * @param {Function} func The function to have its output memoized.
+ * @param {Function} [resolver] The function to resolve the cache key.
+ * @returns {Function} Returns the new memoizing function.
* @example
*
- * _.flattenDeep([1, [2, 3, [4]]]);
- * // => [1, 2, 3, 4]
- */
- function flattenDeep(array) {
- var length = array ? array.length : 0;
- return length ? baseFlatten(array, true) : [];
- }
-
- /**
- * Gets the index at which the first occurrence of `value` is found in `array`
- * using `SameValueZero` for equality comparisons. If `fromIndex` is negative,
- * it is used as the offset from the end of `array`. If `array` is sorted
- * providing `true` for `fromIndex` performs a faster binary search.
+ * var upperCase = _.memoize(function(string) {
+ * return string.toUpperCase();
+ * });
*
- * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
- * comparisons are like strict equality comparisons, e.g. `===`, except that
- * `NaN` matches `NaN`.
+ * upperCase('fred');
+ * // => 'FRED'
*
- * @static
- * @memberOf _
- * @category Array
- * @param {Array} array The array to search.
- * @param {*} value The value to search for.
- * @param {boolean|number} [fromIndex=0] The index to search from or `true`
- * to perform a binary search on a sorted array.
- * @returns {number} Returns the index of the matched value, else `-1`.
- * @example
+ * // modifying the result cache
+ * upperCase.cache.set('fred', 'BARNEY');
+ * upperCase('fred');
+ * // => 'BARNEY'
*
- * _.indexOf([1, 2, 1, 2], 2);
- * // => 1
+ * // replacing `_.memoize.Cache`
+ * var object = { 'user': 'fred' };
+ * var other = { 'user': 'barney' };
+ * var identity = _.memoize(_.identity);
*
- * // using `fromIndex`
- * _.indexOf([1, 2, 1, 2], 2, 2);
- * // => 3
+ * identity(object);
+ * // => { 'user': 'fred' }
+ * identity(other);
+ * // => { 'user': 'fred' }
*
- * // performing a binary search
- * _.indexOf([1, 1, 2, 2], 2, true);
- * // => 2
+ * _.memoize.Cache = WeakMap;
+ * var identity = _.memoize(_.identity);
+ *
+ * identity(object);
+ * // => { 'user': 'fred' }
+ * identity(other);
+ * // => { 'user': 'barney' }
*/
- function indexOf(array, value, fromIndex) {
- var length = array ? array.length : 0;
- if (!length) {
- return -1;
+ function memoize(func, resolver) {
+ if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
+ throw new TypeError(FUNC_ERROR_TEXT);
}
- if (typeof fromIndex == 'number') {
- fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
- } else if (fromIndex) {
- var index = binaryIndex(array, value),
- other = array[index];
+ var memoized = function() {
+ var args = arguments,
+ cache = memoized.cache,
+ key = resolver ? resolver.apply(this, args) : args[0];
- if (value === value ? (value === other) : (other !== other)) {
- return index;
+ if (cache.has(key)) {
+ return cache.get(key);
}
- return -1;
- }
- return baseIndexOf(array, value, fromIndex || 0);
+ var result = func.apply(this, args);
+ cache.set(key, result);
+ return result;
+ };
+ memoized.cache = new memoize.Cache;
+ return memoized;
}
/**
- * Gets all but the last element of `array`.
+ * Creates a function that negates the result of the predicate `func`. The
+ * `func` predicate is invoked with the `this` binding and arguments of the
+ * created function.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @returns {Array} Returns the slice of `array`.
+ * @category Function
+ * @param {Function} predicate The predicate to negate.
+ * @returns {Function} Returns the new function.
* @example
*
- * _.initial([1, 2, 3]);
- * // => [1, 2]
+ * function isEven(n) {
+ * return n % 2 == 0;
+ * }
+ *
+ * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
+ * // => [1, 3, 5]
*/
- function initial(array) {
- return dropRight(array, 1);
+ function negate(predicate) {
+ if (typeof predicate != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
}
/**
- * Creates an array of unique values in all provided arrays using `SameValueZero`
- * for equality comparisons.
- *
- * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
- * comparisons are like strict equality comparisons, e.g. `===`, except that
- * `NaN` matches `NaN`.
+ * Creates a function that is restricted to invoking `func` once. Repeat calls
+ * to the function return the value of the first call. The `func` is invoked
+ * with the `this` binding and arguments of the created function.
*
* @static
* @memberOf _
- * @category Array
- * @param {...Array} [arrays] The arrays to inspect.
- * @returns {Array} Returns the new array of shared values.
+ * @category Function
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
* @example
- * _.intersection([1, 2], [4, 2], [2, 1]);
- * // => [2]
+ *
+ * var initialize = _.once(createApplication);
+ * initialize();
+ * initialize();
+ * // `initialize` invokes `createApplication` once
*/
- function intersection() {
- var args = [],
- argsIndex = -1,
- argsLength = arguments.length,
- caches = [],
- indexOf = getIndexOf(),
- isCommon = indexOf == baseIndexOf,
- result = [];
-
- while (++argsIndex < argsLength) {
- var value = arguments[argsIndex];
- if (isArray(value) || isArguments(value)) {
- args.push(value);
- caches.push((isCommon && value.length >= 120) ? createCache(argsIndex && value) : null);
- }
- }
- argsLength = args.length;
- if (argsLength < 2) {
- return result;
- }
- var array = args[0],
- index = -1,
- length = array ? array.length : 0,
- seen = caches[0];
-
- outer:
- while (++index < length) {
- value = array[index];
- if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) {
- argsIndex = argsLength;
- while (--argsIndex) {
- var cache = caches[argsIndex];
- if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value, 0)) < 0) {
- continue outer;
- }
- }
- if (seen) {
- seen.push(value);
- }
- result.push(value);
- }
- }
- return result;
+ function once(func) {
+ return before(2, func);
}
/**
- * Gets the last element of `array`.
+ * Creates a function that invokes `func` with `partial` arguments prepended
+ * to those provided to the new function. This method is like `_.bind` except
+ * it does **not** alter the `this` binding.
+ *
+ * The `_.partial.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method does not set the "length" property of partially
+ * applied functions.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @returns {*} Returns the last element of `array`.
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
* @example
*
- * _.last([1, 2, 3]);
- * // => 3
+ * var greet = function(greeting, name) {
+ * return greeting + ' ' + name;
+ * };
+ *
+ * var sayHelloTo = _.partial(greet, 'hello');
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ *
+ * // using placeholders
+ * var greetFred = _.partial(greet, _, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
*/
- function last(array) {
- var length = array ? array.length : 0;
- return length ? array[length - 1] : undefined;
- }
+ var partial = createPartial(PARTIAL_FLAG);
/**
- * This method is like `_.indexOf` except that it iterates over elements of
- * `array` from right to left.
+ * This method is like `_.partial` except that partially applied arguments
+ * are appended to those provided to the new function.
+ *
+ * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method does not set the "length" property of partially
+ * applied functions.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to search.
- * @param {*} value The value to search for.
- * @param {boolean|number} [fromIndex=array.length-1] The index to search from
- * or `true` to perform a binary search on a sorted array.
- * @returns {number} Returns the index of the matched value, else `-1`.
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
* @example
*
- * _.lastIndexOf([1, 2, 1, 2], 2);
- * // => 3
+ * var greet = function(greeting, name) {
+ * return greeting + ' ' + name;
+ * };
*
- * // using `fromIndex`
- * _.lastIndexOf([1, 2, 1, 2], 2, 2);
- * // => 1
+ * var greetFred = _.partialRight(greet, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
*
- * // performing a binary search
- * _.lastIndexOf([1, 1, 2, 2], 2, true);
- * // => 3
- */
- function lastIndexOf(array, value, fromIndex) {
- var length = array ? array.length : 0;
- if (!length) {
- return -1;
- }
- var index = length;
- if (typeof fromIndex == 'number') {
- index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1;
- } else if (fromIndex) {
- index = binaryIndex(array, value, true) - 1;
- var other = array[index];
- if (value === value ? (value === other) : (other !== other)) {
- return index;
- }
- return -1;
- }
- if (value !== value) {
- return indexOfNaN(array, index, true);
- }
- while (index--) {
- if (array[index] === value) {
- return index;
- }
- }
- return -1;
- }
-
- /**
- * Removes all provided values from `array` using `SameValueZero` for equality
- * comparisons.
- *
- * **Notes:**
- * - Unlike `_.without`, this method mutates `array`
- * - [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
- * comparisons are like strict equality comparisons, e.g. `===`, except
- * that `NaN` matches `NaN`
- *
- * @static
- * @memberOf _
- * @category Array
- * @param {Array} array The array to modify.
- * @param {...*} [values] The values to remove.
- * @returns {Array} Returns `array`.
- * @example
- *
- * var array = [1, 2, 3, 1, 2, 3];
- *
- * _.pull(array, 2, 3);
- * console.log(array);
- * // => [1, 1]
+ * // using placeholders
+ * var sayHelloTo = _.partialRight(greet, 'hello', _);
+ * sayHelloTo('fred');
+ * // => 'hello fred'
*/
- function pull() {
- var args = arguments,
- array = args[0];
-
- if (!(array && array.length)) {
- return array;
- }
- var index = 0,
- indexOf = getIndexOf(),
- length = args.length;
-
- while (++index < length) {
- var fromIndex = 0,
- value = args[index];
-
- while ((fromIndex = indexOf(array, value, fromIndex)) > -1) {
- splice.call(array, fromIndex, 1);
- }
- }
- return array;
- }
+ var partialRight = createPartial(PARTIAL_RIGHT_FLAG);
/**
- * Removes elements from `array` corresponding to the given indexes and returns
- * an array of the removed elements. Indexes may be specified as an array of
- * indexes or as individual arguments.
- *
- * **Note:** Unlike `_.at`, this method mutates `array`.
+ * Creates a function that invokes `func` with arguments arranged according
+ * to the specified indexes where the argument value at the first index is
+ * provided as the first argument, the argument value at the second index is
+ * provided as the second argument, and so on.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to modify.
- * @param {...(number|number[])} [indexes] The indexes of elements to remove,
+ * @category Function
+ * @param {Function} func The function to rearrange arguments for.
+ * @param {...(number|number[])} indexes The arranged argument indexes,
* specified as individual indexes or arrays of indexes.
- * @returns {Array} Returns the new array of removed elements.
+ * @returns {Function} Returns the new function.
* @example
*
- * var array = [5, 10, 15, 20];
- * var evens = _.pullAt(array, 1, 3);
+ * var rearged = _.rearg(function(a, b, c) {
+ * return [a, b, c];
+ * }, 2, 0, 1);
*
- * console.log(array);
- * // => [5, 15]
+ * rearged('b', 'c', 'a')
+ * // => ['a', 'b', 'c']
*
- * console.log(evens);
- * // => [10, 20]
+ * var map = _.rearg(_.map, [1, 0]);
+ * map(function(n) {
+ * return n * 3;
+ * }, [1, 2, 3]);
+ * // => [3, 6, 9]
*/
- var pullAt = restParam(function(array, indexes) {
- array || (array = []);
- indexes = baseFlatten(indexes);
-
- var result = baseAt(array, indexes);
- basePullAt(array, indexes.sort(baseCompareAscending));
- return result;
+ var rearg = restParam(function(func, indexes) {
+ return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes));
});
/**
- * Removes all elements from `array` that `predicate` returns truthy for
- * and returns an array of the removed elements. The predicate is bound to
- * `thisArg` and invoked with three arguments: (value, index, array).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * Creates a function that invokes `func` with the `this` binding of the
+ * created function and arguments from `start` and beyond provided as an array.
*
- * **Note:** Unlike `_.filter`, this method mutates `array`.
+ * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to modify.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the new array of removed elements.
+ * @category Function
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
* @example
*
- * var array = [1, 2, 3, 4];
- * var evens = _.remove(array, function(n) {
- * return n % 2 == 0;
+ * var say = _.restParam(function(what, names) {
+ * return what + ' ' + _.initial(names).join(', ') +
+ * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
* });
*
- * console.log(array);
- * // => [1, 3]
- *
- * console.log(evens);
- * // => [2, 4]
+ * say('hello', 'fred', 'barney', 'pebbles');
+ * // => 'hello fred, barney, & pebbles'
*/
- function remove(array, predicate, thisArg) {
- var result = [];
- if (!(array && array.length)) {
- return result;
+ function restParam(func, start) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
}
- var index = -1,
- indexes = [],
- length = array.length;
+ start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
+ return function() {
+ var args = arguments,
+ index = -1,
+ length = nativeMax(args.length - start, 0),
+ rest = Array(length);
- predicate = getCallback(predicate, thisArg, 3);
- while (++index < length) {
- var value = array[index];
- if (predicate(value, index, array)) {
- result.push(value);
- indexes.push(index);
+ while (++index < length) {
+ rest[index] = args[start + index];
}
- }
- basePullAt(array, indexes);
- return result;
+ switch (start) {
+ case 0: return func.call(this, rest);
+ case 1: return func.call(this, args[0], rest);
+ case 2: return func.call(this, args[0], args[1], rest);
+ }
+ var otherArgs = Array(start + 1);
+ index = -1;
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = rest;
+ return func.apply(this, otherArgs);
+ };
}
/**
- * Gets all but the first element of `array`.
+ * Creates a function that invokes `func` with the `this` binding of the created
+ * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3).
+ *
+ * **Note:** This method is based on the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator).
*
* @static
* @memberOf _
- * @alias tail
- * @category Array
- * @param {Array} array The array to query.
- * @returns {Array} Returns the slice of `array`.
+ * @category Function
+ * @param {Function} func The function to spread arguments over.
+ * @returns {Function} Returns the new function.
* @example
*
- * _.rest([1, 2, 3]);
- * // => [2, 3]
+ * var say = _.spread(function(who, what) {
+ * return who + ' says ' + what;
+ * });
+ *
+ * say(['fred', 'hello']);
+ * // => 'fred says hello'
+ *
+ * // with a Promise
+ * var numbers = Promise.all([
+ * Promise.resolve(40),
+ * Promise.resolve(36)
+ * ]);
+ *
+ * numbers.then(_.spread(function(x, y) {
+ * return x + y;
+ * }));
+ * // => a Promise of 76
*/
- function rest(array) {
- return drop(array, 1);
+ function spread(func) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return function(array) {
+ return func.apply(this, array);
+ };
}
/**
- * Creates a slice of `array` from `start` up to, but not including, `end`.
+ * Creates a function that only invokes `func` at most once per every `wait`
+ * milliseconds. The created function comes with a `cancel` method to cancel
+ * delayed invocations. Provide an options object to indicate that `func`
+ * should be invoked on the leading and/or trailing edge of the `wait` timeout.
+ * Subsequent calls to the throttled function return the result of the last
+ * `func` call.
*
- * **Note:** This method is used instead of `Array#slice` to support node
- * lists in IE < 9 and to ensure dense arrays are returned.
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
+ * on the trailing edge of the timeout only if the the throttled function is
+ * invoked more than once during the `wait` timeout.
+ *
+ * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
+ * for details over the differences between `_.throttle` and `_.debounce`.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to slice.
- * @param {number} [start=0] The start position.
- * @param {number} [end=array.length] The end position.
- * @returns {Array} Returns the slice of `array`.
- */
- function slice(array, start, end) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
+ * @category Function
+ * @param {Function} func The function to throttle.
+ * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.leading=true] Specify invoking on the leading
+ * edge of the timeout.
+ * @param {boolean} [options.trailing=true] Specify invoking on the trailing
+ * edge of the timeout.
+ * @returns {Function} Returns the new throttled function.
+ * @example
+ *
+ * // avoid excessively updating the position while scrolling
+ * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
+ *
+ * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
+ * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
+ * 'trailing': false
+ * }));
+ *
+ * // cancel a trailing throttled call
+ * jQuery(window).on('popstate', throttled.cancel);
+ */
+ function throttle(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
}
- if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
- start = 0;
- end = length;
+ if (options === false) {
+ leading = false;
+ } else if (isObject(options)) {
+ leading = 'leading' in options ? !!options.leading : leading;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
}
- return baseSlice(array, start, end);
+ debounceOptions.leading = leading;
+ debounceOptions.maxWait = +wait;
+ debounceOptions.trailing = trailing;
+ return debounce(func, wait, debounceOptions);
}
/**
- * Uses a binary search to determine the lowest index at which `value` should
- * be inserted into `array` in order to maintain its sort order. If an iteratee
- * function is provided it is invoked for `value` and each element of `array`
- * to compute their sort ranking. The iteratee is bound to `thisArg` and
- * invoked with one argument; (value).
+ * Creates a function that provides `value` to the wrapper function as its
+ * first argument. Any additional arguments provided to the function are
+ * appended to those provided to the wrapper function. The wrapper is invoked
+ * with the `this` binding of the created function.
*
- * If a property name is provided for `iteratee` the created `_.property`
- * style callback returns the property value of the given element.
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {*} value The value to wrap.
+ * @param {Function} wrapper The wrapper function.
+ * @returns {Function} Returns the new function.
+ * @example
*
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
+ * var p = _.wrap(_.escape, function(func, text) {
+ * return '
' + func(text) + '
';
+ * });
*
- * If an object is provided for `iteratee` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * p('fred, barney, & pebbles');
+ * // => '
fred, barney, & pebbles
'
+ */
+ function wrap(value, wrapper) {
+ wrapper = wrapper == null ? identity : wrapper;
+ return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []);
+ }
+
+ /**
+ * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned,
+ * otherwise they are assigned by reference. If `customizer` is provided it is
+ * invoked to produce the cloned values. If `customizer` returns `undefined`
+ * cloning is handled by the method instead. The `customizer` is bound to
+ * `thisArg` and invoked with two argument; (value [, index|key, object]).
+ *
+ * **Note:** This method is loosely based on the
+ * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
+ * The enumerable properties of `arguments` objects and objects created by
+ * constructors other than `Object` are cloned to plain `Object` objects. An
+ * empty object is returned for uncloneable values such as functions, DOM nodes,
+ * Maps, Sets, and WeakMaps.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The sorted array to inspect.
- * @param {*} value The value to evaluate.
- * @param {Function|Object|string} [iteratee=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {number} Returns the index at which `value` should be inserted
- * into `array`.
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @param {Function} [customizer] The function to customize cloning values.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {*} Returns the cloned value.
* @example
*
- * _.sortedIndex([30, 50], 40);
- * // => 1
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
*
- * _.sortedIndex([4, 4, 5, 5], 5);
- * // => 2
+ * var shallow = _.clone(users);
+ * shallow[0] === users[0];
+ * // => true
*
- * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } };
+ * var deep = _.clone(users, true);
+ * deep[0] === users[0];
+ * // => false
*
- * // using an iteratee function
- * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) {
- * return this.data[word];
- * }, dict);
- * // => 1
+ * // using a customizer callback
+ * var el = _.clone(document.body, function(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(false);
+ * }
+ * });
*
- * // using the `_.property` callback shorthand
- * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
- * // => 1
+ * el === document.body
+ * // => false
+ * el.nodeName
+ * // => BODY
+ * el.childNodes.length;
+ * // => 0
*/
- var sortedIndex = createSortedIndex();
+ function clone(value, isDeep, customizer, thisArg) {
+ if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {
+ isDeep = false;
+ }
+ else if (typeof isDeep == 'function') {
+ thisArg = customizer;
+ customizer = isDeep;
+ isDeep = false;
+ }
+ customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1);
+ return baseClone(value, isDeep, customizer);
+ }
/**
- * This method is like `_.sortedIndex` except that it returns the highest
- * index at which `value` should be inserted into `array` in order to
- * maintain its sort order.
+ * Creates a deep clone of `value`. If `customizer` is provided it is invoked
+ * to produce the cloned values. If `customizer` returns `undefined` cloning
+ * is handled by the method instead. The `customizer` is bound to `thisArg`
+ * and invoked with two argument; (value [, index|key, object]).
+ *
+ * **Note:** This method is loosely based on the
+ * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
+ * The enumerable properties of `arguments` objects and objects created by
+ * constructors other than `Object` are cloned to plain `Object` objects. An
+ * empty object is returned for uncloneable values such as functions, DOM nodes,
+ * Maps, Sets, and WeakMaps.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The sorted array to inspect.
- * @param {*} value The value to evaluate.
- * @param {Function|Object|string} [iteratee=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {number} Returns the index at which `value` should be inserted
- * into `array`.
+ * @category Lang
+ * @param {*} value The value to deep clone.
+ * @param {Function} [customizer] The function to customize cloning values.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {*} Returns the deep cloned value.
* @example
*
- * _.sortedLastIndex([4, 4, 5, 5], 5);
- * // => 4
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * var deep = _.cloneDeep(users);
+ * deep[0] === users[0];
+ * // => false
+ *
+ * // using a customizer callback
+ * var el = _.cloneDeep(document.body, function(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(true);
+ * }
+ * });
+ *
+ * el === document.body
+ * // => false
+ * el.nodeName
+ * // => BODY
+ * el.childNodes.length;
+ * // => 20
*/
- var sortedLastIndex = createSortedIndex(true);
+ function cloneDeep(value, customizer, thisArg) {
+ customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1);
+ return baseClone(value, true, customizer);
+ }
/**
- * Creates a slice of `array` with `n` elements taken from the beginning.
+ * Checks if `value` is classified as an `arguments` object.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @param {number} [n=1] The number of elements to take.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Array} Returns the slice of `array`.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @example
*
- * _.take([1, 2, 3]);
- * // => [1]
- *
- * _.take([1, 2, 3], 2);
- * // => [1, 2]
- *
- * _.take([1, 2, 3], 5);
- * // => [1, 2, 3]
+ * _.isArguments(function() { return arguments; }());
+ * // => true
*
- * _.take([1, 2, 3], 0);
- * // => []
+ * _.isArguments([1, 2, 3]);
+ * // => false
*/
- function take(array, n, guard) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
- if (guard ? isIterateeCall(array, n, guard) : n == null) {
- n = 1;
- }
- return baseSlice(array, 0, n < 0 ? 0 : n);
+ function isArguments(value) {
+ return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag;
}
/**
- * Creates a slice of `array` with `n` elements taken from the end.
+ * Checks if `value` is classified as an `Array` object.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @param {number} [n=1] The number of elements to take.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Array} Returns the slice of `array`.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @example
*
- * _.takeRight([1, 2, 3]);
- * // => [3]
- *
- * _.takeRight([1, 2, 3], 2);
- * // => [2, 3]
- *
- * _.takeRight([1, 2, 3], 5);
- * // => [1, 2, 3]
+ * _.isArray([1, 2, 3]);
+ * // => true
*
- * _.takeRight([1, 2, 3], 0);
- * // => []
+ * _.isArray(function() { return arguments; }());
+ * // => false
*/
- function takeRight(array, n, guard) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
- if (guard ? isIterateeCall(array, n, guard) : n == null) {
- n = 1;
- }
- n = length - (+n || 0);
- return baseSlice(array, n < 0 ? 0 : n);
- }
+ var isArray = nativeIsArray || function(value) {
+ return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
+ };
/**
- * Creates a slice of `array` with elements taken from the end. Elements are
- * taken until `predicate` returns falsey. The predicate is bound to `thisArg`
- * and invoked with three arguments: (value, index, array).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * Checks if `value` is classified as a boolean primitive or object.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the slice of `array`.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @example
*
- * _.takeRightWhile([1, 2, 3], function(n) {
- * return n > 1;
- * });
- * // => [2, 3]
- *
- * var users = [
- * { 'user': 'barney', 'active': true },
- * { 'user': 'fred', 'active': false },
- * { 'user': 'pebbles', 'active': false }
- * ];
- *
- * // using the `_.matches` callback shorthand
- * _.pluck(_.takeRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
- * // => ['pebbles']
- *
- * // using the `_.matchesProperty` callback shorthand
- * _.pluck(_.takeRightWhile(users, 'active', false), 'user');
- * // => ['fred', 'pebbles']
+ * _.isBoolean(false);
+ * // => true
*
- * // using the `_.property` callback shorthand
- * _.pluck(_.takeRightWhile(users, 'active'), 'user');
- * // => []
+ * _.isBoolean(null);
+ * // => false
*/
- function takeRightWhile(array, predicate, thisArg) {
- return (array && array.length)
- ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true)
- : [];
+ function isBoolean(value) {
+ return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag);
}
/**
- * Creates a slice of `array` with elements taken from the beginning. Elements
- * are taken until `predicate` returns falsey. The predicate is bound to
- * `thisArg` and invoked with three arguments: (value, index, array).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * Checks if `value` is classified as a `Date` object.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array to query.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the slice of `array`.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @example
*
- * _.takeWhile([1, 2, 3], function(n) {
- * return n < 3;
- * });
- * // => [1, 2]
- *
- * var users = [
- * { 'user': 'barney', 'active': false },
- * { 'user': 'fred', 'active': false},
- * { 'user': 'pebbles', 'active': true }
- * ];
- *
- * // using the `_.matches` callback shorthand
- * _.pluck(_.takeWhile(users, { 'user': 'barney', 'active': false }), 'user');
- * // => ['barney']
- *
- * // using the `_.matchesProperty` callback shorthand
- * _.pluck(_.takeWhile(users, 'active', false), 'user');
- * // => ['barney', 'fred']
+ * _.isDate(new Date);
+ * // => true
*
- * // using the `_.property` callback shorthand
- * _.pluck(_.takeWhile(users, 'active'), 'user');
- * // => []
+ * _.isDate('Mon April 23 2012');
+ * // => false
*/
- function takeWhile(array, predicate, thisArg) {
- return (array && array.length)
- ? baseWhile(array, getCallback(predicate, thisArg, 3))
- : [];
+ function isDate(value) {
+ return isObjectLike(value) && objToString.call(value) == dateTag;
}
/**
- * Creates an array of unique values, in order, of the provided arrays using
- * `SameValueZero` for equality comparisons.
- *
- * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
- * comparisons are like strict equality comparisons, e.g. `===`, except that
- * `NaN` matches `NaN`.
+ * Checks if `value` is a DOM element.
*
* @static
* @memberOf _
- * @category Array
- * @param {...Array} [arrays] The arrays to inspect.
- * @returns {Array} Returns the new array of combined values.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
* @example
*
- * _.union([1, 2], [4, 2], [2, 1]);
- * // => [1, 2, 4]
+ * _.isElement(document.body);
+ * // => true
+ *
+ * _.isElement('');
+ * // => false
*/
- var union = restParam(function(arrays) {
- return baseUniq(baseFlatten(arrays, false, true));
- });
+ function isElement(value) {
+ return !!value && value.nodeType === 1 && isObjectLike(value) &&
+ (objToString.call(value).indexOf('Element') > -1);
+ }
+ // Fallback for environments without DOM support.
+ if (!support.dom) {
+ isElement = function(value) {
+ return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
+ };
+ }
/**
- * Creates a duplicate-free version of an array, using `SameValueZero` for
- * equality comparisons, in which only the first occurence of each element
- * is kept. Providing `true` for `isSorted` performs a faster search algorithm
- * for sorted arrays. If an iteratee function is provided it is invoked for
- * each element in the array to generate the criterion by which uniqueness
- * is computed. The `iteratee` is bound to `thisArg` and invoked with three
- * arguments: (value, index, array).
- *
- * If a property name is provided for `iteratee` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `iteratee` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
- *
- * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
- * comparisons are like strict equality comparisons, e.g. `===`, except that
- * `NaN` matches `NaN`.
+ * Checks if `value` is empty. A value is considered empty unless it is an
+ * `arguments` object, array, string, or jQuery-like collection with a length
+ * greater than `0` or an object with own enumerable properties.
*
* @static
* @memberOf _
- * @alias unique
- * @category Array
- * @param {Array} array The array to inspect.
- * @param {boolean} [isSorted] Specify the array is sorted.
- * @param {Function|Object|string} [iteratee] The function invoked per iteration.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {Array} Returns the new duplicate-value-free array.
+ * @category Lang
+ * @param {Array|Object|string} value The value to inspect.
+ * @returns {boolean} Returns `true` if `value` is empty, else `false`.
* @example
*
- * _.uniq([2, 1, 2]);
- * // => [2, 1]
+ * _.isEmpty(null);
+ * // => true
*
- * // using `isSorted`
- * _.uniq([1, 1, 2], true);
- * // => [1, 2]
+ * _.isEmpty(true);
+ * // => true
*
- * // using an iteratee function
- * _.uniq([1, 2.5, 1.5, 2], function(n) {
- * return this.floor(n);
- * }, Math);
- * // => [1, 2.5]
+ * _.isEmpty(1);
+ * // => true
*
- * // using the `_.property` callback shorthand
- * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
- * // => [{ 'x': 1 }, { 'x': 2 }]
+ * _.isEmpty([1, 2, 3]);
+ * // => false
+ *
+ * _.isEmpty({ 'a': 1 });
+ * // => false
*/
- function uniq(array, isSorted, iteratee, thisArg) {
- var length = array ? array.length : 0;
- if (!length) {
- return [];
- }
- if (isSorted != null && typeof isSorted != 'boolean') {
- thisArg = iteratee;
- iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted;
- isSorted = false;
+ function isEmpty(value) {
+ if (value == null) {
+ return true;
}
- var func = getCallback();
- if (!(func === baseCallback && iteratee == null)) {
- iteratee = func(iteratee, thisArg, 3);
+ if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) ||
+ (isObjectLike(value) && isFunction(value.splice)))) {
+ return !value.length;
}
- return (isSorted && getIndexOf() == baseIndexOf)
- ? sortedUniq(array, iteratee)
- : baseUniq(array, iteratee);
+ return !keys(value).length;
}
/**
- * This method is like `_.zip` except that it accepts an array of grouped
- * elements and creates an array regrouping the elements to their pre-`_.zip`
- * configuration.
+ * Performs a deep comparison between two values to determine if they are
+ * equivalent. If `customizer` is provided it is invoked to compare values.
+ * If `customizer` returns `undefined` comparisons are handled by the method
+ * instead. The `customizer` is bound to `thisArg` and invoked with three
+ * arguments: (value, other [, index|key]).
+ *
+ * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+ * numbers, `Object` objects, regexes, and strings. Objects are compared by
+ * their own, not inherited, enumerable properties. Functions and DOM nodes
+ * are **not** supported. Provide a customizer function to extend support
+ * for comparing other values.
*
* @static
* @memberOf _
- * @category Array
- * @param {Array} array The array of grouped elements to process.
- * @returns {Array} Returns the new array of regrouped elements.
- * @example
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {Function} [customizer] The function to customize value comparisons.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
*
- * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
- * // => [['fred', 30, true], ['barney', 40, false]]
+ * var object = { 'user': 'fred' };
+ * var other = { 'user': 'fred' };
*
- * _.unzip(zipped);
- * // => [['fred', 'barney'], [30, 40], [true, false]]
- */
- function unzip(array) {
- var index = -1,
- length = (array && array.length && arrayMax(arrayMap(array, getLength))) >>> 0,
- result = Array(length);
-
- while (++index < length) {
- result[index] = arrayMap(array, baseProperty(index));
- }
- return result;
- }
-
- /**
- * Creates an array excluding all provided values using `SameValueZero` for
- * equality comparisons.
+ * object == other;
+ * // => false
*
- * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
- * comparisons are like strict equality comparisons, e.g. `===`, except that
- * `NaN` matches `NaN`.
+ * _.isEqual(object, other);
+ * // => true
*
- * @static
- * @memberOf _
- * @category Array
- * @param {Array} array The array to filter.
- * @param {...*} [values] The values to exclude.
- * @returns {Array} Returns the new array of filtered values.
- * @example
+ * // using a customizer callback
+ * var array = ['hello', 'goodbye'];
+ * var other = ['hi', 'goodbye'];
*
- * _.without([1, 2, 1, 3], 1, 2);
- * // => [3]
+ * _.isEqual(array, other, function(value, other) {
+ * if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) {
+ * return true;
+ * }
+ * });
+ * // => true
*/
- var without = restParam(function(array, values) {
- return (isArray(array) || isArguments(array))
- ? baseDifference(array, values)
- : [];
- });
+ function isEqual(value, other, customizer, thisArg) {
+ customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3);
+ if (!customizer && isStrictComparable(value) && isStrictComparable(other)) {
+ return value === other;
+ }
+ var result = customizer ? customizer(value, other) : undefined;
+ return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
+ }
/**
- * Creates an array that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
- * of the provided arrays.
+ * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
+ * `SyntaxError`, `TypeError`, or `URIError` object.
*
* @static
* @memberOf _
- * @category Array
- * @param {...Array} [arrays] The arrays to inspect.
- * @returns {Array} Returns the new array of values.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
* @example
*
- * _.xor([1, 2], [4, 2]);
- * // => [1, 4]
+ * _.isError(new Error);
+ * // => true
+ *
+ * _.isError(Error);
+ * // => false
*/
- function xor() {
- var index = -1,
- length = arguments.length;
-
- while (++index < length) {
- var array = arguments[index];
- if (isArray(array) || isArguments(array)) {
- var result = result
- ? baseDifference(result, array).concat(baseDifference(array, result))
- : array;
- }
- }
- return result ? baseUniq(result) : [];
+ function isError(value) {
+ return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag;
}
/**
- * Creates an array of grouped elements, the first of which contains the first
- * elements of the given arrays, the second of which contains the second elements
- * of the given arrays, and so on.
+ * Checks if `value` is a finite primitive number.
+ *
+ * **Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite).
*
* @static
* @memberOf _
- * @category Array
- * @param {...Array} [arrays] The arrays to process.
- * @returns {Array} Returns the new array of grouped elements.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
* @example
*
- * _.zip(['fred', 'barney'], [30, 40], [true, false]);
- * // => [['fred', 30, true], ['barney', 40, false]]
- */
- var zip = restParam(unzip);
-
- /**
- * The inverse of `_.pairs`; this method returns an object composed from arrays
- * of property names and values. Provide either a single two dimensional array,
- * e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names
- * and one of corresponding values.
+ * _.isFinite(10);
+ * // => true
*
- * @static
- * @memberOf _
- * @alias object
- * @category Array
- * @param {Array} props The property names.
- * @param {Array} [values=[]] The property values.
- * @returns {Object} Returns the new object.
- * @example
+ * _.isFinite('10');
+ * // => false
*
- * _.zipObject([['fred', 30], ['barney', 40]]);
- * // => { 'fred': 30, 'barney': 40 }
+ * _.isFinite(true);
+ * // => false
*
- * _.zipObject(['fred', 'barney'], [30, 40]);
- * // => { 'fred': 30, 'barney': 40 }
+ * _.isFinite(Object(10));
+ * // => false
+ *
+ * _.isFinite(Infinity);
+ * // => false
*/
- function zipObject(props, values) {
- var index = -1,
- length = props ? props.length : 0,
- result = {};
-
- if (length && !values && !isArray(props[0])) {
- values = [];
- }
- while (++index < length) {
- var key = props[index];
- if (values) {
- result[key] = values[index];
- } else if (key) {
- result[key[0]] = key[1];
- }
- }
- return result;
- }
-
- /*------------------------------------------------------------------------*/
+ var isFinite = nativeNumIsFinite || function(value) {
+ return typeof value == 'number' && nativeIsFinite(value);
+ };
/**
- * Creates a `lodash` object that wraps `value` with explicit method
- * chaining enabled.
+ * Checks if `value` is classified as a `Function` object.
*
* @static
* @memberOf _
- * @category Chain
- * @param {*} value The value to wrap.
- * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @example
*
- * var users = [
- * { 'user': 'barney', 'age': 36 },
- * { 'user': 'fred', 'age': 40 },
- * { 'user': 'pebbles', 'age': 1 }
- * ];
+ * _.isFunction(_);
+ * // => true
*
- * var youngest = _.chain(users)
- * .sortBy('age')
- * .map(function(chr) {
- * return chr.user + ' is ' + chr.age;
- * })
- * .first()
- * .value();
- * // => 'pebbles is 1'
+ * _.isFunction(/abc/);
+ * // => false
*/
- function chain(value) {
- var result = lodash(value);
- result.__chain__ = true;
- return result;
- }
+ var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in older versions of Chrome and Safari which return 'function' for regexes
+ // and Safari 8 equivalents which return 'object' for typed array constructors.
+ return objToString.call(value) == funcTag;
+ };
/**
- * This method invokes `interceptor` and returns `value`. The interceptor is
- * bound to `thisArg` and invoked with one argument; (value). The purpose of
- * this method is to "tap into" a method chain in order to perform operations
- * on intermediate results within the chain.
+ * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
- * @category Chain
- * @param {*} value The value to provide to `interceptor`.
- * @param {Function} interceptor The function to invoke.
- * @param {*} [thisArg] The `this` binding of `interceptor`.
- * @returns {*} Returns `value`.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
* @example
*
- * _([1, 2, 3])
- * .tap(function(array) {
- * array.pop();
- * })
- * .reverse()
- * .value();
- * // => [2, 1]
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(1);
+ * // => false
*/
- function tap(value, interceptor, thisArg) {
- interceptor.call(thisArg, value);
- return value;
+ function isObject(value) {
+ // Avoid a V8 JIT bug in Chrome 19-20.
+ // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+ var type = typeof value;
+ return type == 'function' || (!!value && type == 'object');
}
/**
- * This method is like `_.tap` except that it returns the result of `interceptor`.
+ * Performs a deep comparison between `object` and `source` to determine if
+ * `object` contains equivalent property values. If `customizer` is provided
+ * it is invoked to compare values. If `customizer` returns `undefined`
+ * comparisons are handled by the method instead. The `customizer` is bound
+ * to `thisArg` and invoked with three arguments: (value, other, index|key).
+ *
+ * **Note:** This method supports comparing properties of arrays, booleans,
+ * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions
+ * and DOM nodes are **not** supported. Provide a customizer function to extend
+ * support for comparing other values.
*
* @static
* @memberOf _
- * @category Chain
- * @param {*} value The value to provide to `interceptor`.
- * @param {Function} interceptor The function to invoke.
- * @param {*} [thisArg] The `this` binding of `interceptor`.
- * @returns {*} Returns the result of `interceptor`.
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Function} [customizer] The function to customize value comparisons.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
* @example
*
- * _(' abc ')
- * .chain()
- * .trim()
- * .thru(function(value) {
- * return [value];
- * })
- * .value();
- * // => ['abc']
- */
- function thru(value, interceptor, thisArg) {
- return interceptor.call(thisArg, value);
- }
-
- /**
- * Enables explicit method chaining on the wrapper object.
+ * var object = { 'user': 'fred', 'age': 40 };
*
- * @name chain
- * @memberOf _
- * @category Chain
- * @returns {Object} Returns the new `lodash` wrapper instance.
- * @example
+ * _.isMatch(object, { 'age': 40 });
+ * // => true
*
- * var users = [
- * { 'user': 'barney', 'age': 36 },
- * { 'user': 'fred', 'age': 40 }
- * ];
+ * _.isMatch(object, { 'age': 36 });
+ * // => false
*
- * // without explicit chaining
- * _(users).first();
- * // => { 'user': 'barney', 'age': 36 }
+ * // using a customizer callback
+ * var object = { 'greeting': 'hello' };
+ * var source = { 'greeting': 'hi' };
*
- * // with explicit chaining
- * _(users).chain()
- * .first()
- * .pick('user')
- * .value();
- * // => { 'user': 'barney' }
+ * _.isMatch(object, source, function(value, other) {
+ * return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined;
+ * });
+ * // => true
*/
- function wrapperChain() {
- return chain(this);
+ function isMatch(object, source, customizer, thisArg) {
+ var props = keys(source),
+ length = props.length;
+
+ if (!length) {
+ return true;
+ }
+ if (object == null) {
+ return false;
+ }
+ customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3);
+ object = toObject(object);
+ if (!customizer && length == 1) {
+ var key = props[0],
+ value = source[key];
+
+ if (isStrictComparable(value)) {
+ return value === object[key] && (value !== undefined || (key in object));
+ }
+ }
+ var values = Array(length),
+ strictCompareFlags = Array(length);
+
+ while (length--) {
+ value = values[length] = source[props[length]];
+ strictCompareFlags[length] = isStrictComparable(value);
+ }
+ return baseIsMatch(object, props, values, strictCompareFlags, customizer);
}
/**
- * Executes the chained sequence and returns the wrapped result.
+ * Checks if `value` is `NaN`.
*
- * @name commit
+ * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4)
+ * which returns `true` for `undefined` and other non-numeric values.
+ *
+ * @static
* @memberOf _
- * @category Chain
- * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
* @example
*
- * var array = [1, 2];
- * var wrapper = _(array).push(3);
- *
- * console.log(array);
- * // => [1, 2]
+ * _.isNaN(NaN);
+ * // => true
*
- * wrapper = wrapper.commit();
- * console.log(array);
- * // => [1, 2, 3]
+ * _.isNaN(new Number(NaN));
+ * // => true
*
- * wrapper.last();
- * // => 3
+ * isNaN(undefined);
+ * // => true
*
- * console.log(array);
- * // => [1, 2, 3]
+ * _.isNaN(undefined);
+ * // => false
*/
- function wrapperCommit() {
- return new LodashWrapper(this.value(), this.__chain__);
+ function isNaN(value) {
+ // An `NaN` primitive is the only value that is not equal to itself.
+ // Perform the `toStringTag` check first to avoid errors with some host objects in IE.
+ return isNumber(value) && value != +value;
}
/**
- * Creates a clone of the chained sequence planting `value` as the wrapped value.
+ * Checks if `value` is a native function.
*
- * @name plant
+ * @static
* @memberOf _
- * @category Chain
- * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
* @example
*
- * var array = [1, 2];
- * var wrapper = _(array).map(function(value) {
- * return Math.pow(value, 2);
- * });
- *
- * var other = [3, 4];
- * var otherWrapper = wrapper.plant(other);
- *
- * otherWrapper.value();
- * // => [9, 16]
+ * _.isNative(Array.prototype.push);
+ * // => true
*
- * wrapper.value();
- * // => [1, 4]
+ * _.isNative(_);
+ * // => false
*/
- function wrapperPlant(value) {
- var result,
- parent = this;
-
- while (parent instanceof baseLodash) {
- var clone = wrapperClone(parent);
- if (result) {
- previous.__wrapped__ = clone;
- } else {
- result = clone;
- }
- var previous = clone;
- parent = parent.__wrapped__;
+ function isNative(value) {
+ if (value == null) {
+ return false;
}
- previous.__wrapped__ = value;
- return result;
+ if (objToString.call(value) == funcTag) {
+ return reIsNative.test(fnToString.call(value));
+ }
+ return isObjectLike(value) && reIsHostCtor.test(value);
}
/**
- * Reverses the wrapped array so the first element becomes the last, the
- * second element becomes the second to last, and so on.
- *
- * **Note:** This method mutates the wrapped array.
+ * Checks if `value` is `null`.
*
- * @name reverse
+ * @static
* @memberOf _
- * @category Chain
- * @returns {Object} Returns the new reversed `lodash` wrapper instance.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
* @example
*
- * var array = [1, 2, 3];
- *
- * _(array).reverse().value()
- * // => [3, 2, 1]
+ * _.isNull(null);
+ * // => true
*
- * console.log(array);
- * // => [3, 2, 1]
+ * _.isNull(void 0);
+ * // => false
*/
- function wrapperReverse() {
- var value = this.__wrapped__;
- if (value instanceof LazyWrapper) {
- if (this.__actions__.length) {
- value = new LazyWrapper(this);
- }
- return new LodashWrapper(value.reverse(), this.__chain__);
- }
- return this.thru(function(value) {
- return value.reverse();
- });
+ function isNull(value) {
+ return value === null;
}
/**
- * Produces the result of coercing the unwrapped value to a string.
+ * Checks if `value` is classified as a `Number` primitive or object.
*
- * @name toString
+ * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
+ * as numbers, use the `_.isFinite` method.
+ *
+ * @static
* @memberOf _
- * @category Chain
- * @returns {string} Returns the coerced string value.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @example
*
- * _([1, 2, 3]).toString();
- * // => '1,2,3'
- */
- function wrapperToString() {
- return (this.value() + '');
- }
-
- /**
- * Executes the chained sequence to extract the unwrapped value.
+ * _.isNumber(8.4);
+ * // => true
*
- * @name value
- * @memberOf _
- * @alias run, toJSON, valueOf
- * @category Chain
- * @returns {*} Returns the resolved unwrapped value.
- * @example
+ * _.isNumber(NaN);
+ * // => true
*
- * _([1, 2, 3]).value();
- * // => [1, 2, 3]
+ * _.isNumber('8.4');
+ * // => false
*/
- function wrapperValue() {
- return baseWrapperValue(this.__wrapped__, this.__actions__);
+ function isNumber(value) {
+ return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag);
}
- /*------------------------------------------------------------------------*/
-
/**
- * Creates an array of elements corresponding to the given keys, or indexes,
- * of `collection`. Keys may be specified as individual arguments or as arrays
- * of keys.
+ * Checks if `value` is a plain object, that is, an object created by the
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
+ *
+ * **Note:** This method assumes objects created by the `Object` constructor
+ * have no inherited enumerable properties.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {...(number|number[]|string|string[])} [props] The property names
- * or indexes of elements to pick, specified individually or in arrays.
- * @returns {Array} Returns the new array of picked elements.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
- * _.at(['a', 'b', 'c'], [0, 2]);
- * // => ['a', 'c']
+ * function Foo() {
+ * this.a = 1;
+ * }
*
- * _.at(['barney', 'fred', 'pebbles'], 0, 2);
- * // => ['barney', 'pebbles']
- */
- var at = restParam(function(collection, props) {
- var length = collection ? getLength(collection) : 0;
- if (isLength(length)) {
- collection = toIterable(collection);
+ * _.isPlainObject(new Foo);
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
+ * // => true
+ *
+ * _.isPlainObject(Object.create(null));
+ * // => true
+ */
+ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
+ if (!(value && objToString.call(value) == objectTag)) {
+ return false;
}
- return baseAt(collection, baseFlatten(props));
- });
+ var valueOf = value.valueOf,
+ objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+ return objProto
+ ? (value == objProto || getPrototypeOf(value) == objProto)
+ : shimIsPlainObject(value);
+ };
/**
- * Creates an object composed of keys generated from the results of running
- * each element of `collection` through `iteratee`. The corresponding value
- * of each key is the number of times the key was returned by `iteratee`.
- * The `iteratee` is bound to `thisArg` and invoked with three arguments:
- * (value, index|key, collection).
+ * Checks if `value` is classified as a `RegExp` object.
*
- * If a property name is provided for `iteratee` the created `_.property`
- * style callback returns the property value of the given element.
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
*
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
+ * _.isRegExp(/abc/);
+ * // => true
*
- * If an object is provided for `iteratee` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * _.isRegExp('/abc/');
+ * // => false
+ */
+ function isRegExp(value) {
+ return isObjectLike(value) && objToString.call(value) == regexpTag;
+ }
+
+ /**
+ * Checks if `value` is classified as a `String` primitive or object.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [iteratee=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {Object} Returns the composed aggregate object.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @example
*
- * _.countBy([4.3, 6.1, 6.4], function(n) {
- * return Math.floor(n);
- * });
- * // => { '4': 1, '6': 2 }
- *
- * _.countBy([4.3, 6.1, 6.4], function(n) {
- * return this.floor(n);
- * }, Math);
- * // => { '4': 1, '6': 2 }
+ * _.isString('abc');
+ * // => true
*
- * _.countBy(['one', 'two', 'three'], 'length');
- * // => { '3': 2, '5': 1 }
+ * _.isString(1);
+ * // => false
*/
- var countBy = createAggregator(function(result, value, key) {
- hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
- });
+ function isString(value) {
+ return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
+ }
/**
- * Checks if `predicate` returns truthy for **all** elements of `collection`.
- * The predicate is bound to `thisArg` and invoked with three arguments:
- * (value, index|key, collection).
+ * Checks if `value` is classified as a typed array.
*
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
*
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
+ * _.isTypedArray(new Uint8Array);
+ * // => true
*
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * _.isTypedArray([]);
+ * // => false
+ */
+ function isTypedArray(value) {
+ return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
+ }
+
+ /**
+ * Checks if `value` is `undefined`.
*
* @static
* @memberOf _
- * @alias all
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {boolean} Returns `true` if all elements pass the predicate check,
- * else `false`.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
* @example
*
- * _.every([true, 1, null, 'yes'], Boolean);
- * // => false
- *
- * var users = [
- * { 'user': 'barney', 'active': false },
- * { 'user': 'fred', 'active': false }
- * ];
+ * _.isUndefined(void 0);
+ * // => true
*
- * // using the `_.matches` callback shorthand
- * _.every(users, { 'user': 'barney', 'active': false });
+ * _.isUndefined(null);
* // => false
+ */
+ function isUndefined(value) {
+ return value === undefined;
+ }
+
+ /**
+ * Converts `value` to an array.
*
- * // using the `_.matchesProperty` callback shorthand
- * _.every(users, 'active', false);
- * // => true
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Array} Returns the converted array.
+ * @example
*
- * // using the `_.property` callback shorthand
- * _.every(users, 'active');
- * // => false
+ * (function() {
+ * return _.toArray(arguments).slice(1);
+ * }(1, 2, 3));
+ * // => [2, 3]
*/
- function every(collection, predicate, thisArg) {
- var func = isArray(collection) ? arrayEvery : baseEvery;
- if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
- predicate = null;
+ function toArray(value) {
+ var length = value ? getLength(value) : 0;
+ if (!isLength(length)) {
+ return values(value);
}
- if (typeof predicate != 'function' || thisArg !== undefined) {
- predicate = getCallback(predicate, thisArg, 3);
+ if (!length) {
+ return [];
}
- return func(collection, predicate);
+ return arrayCopy(value);
}
/**
- * Iterates over elements of `collection`, returning an array of all elements
- * `predicate` returns truthy for. The predicate is bound to `thisArg` and
- * invoked with three arguments: (value, index|key, collection).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * Converts `value` to a plain object flattening inherited enumerable
+ * properties of `value` to own properties of the plain object.
*
* @static
* @memberOf _
- * @alias select
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the new filtered array.
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Object} Returns the converted plain object.
* @example
*
- * _.filter([4, 5, 6], function(n) {
- * return n % 2 == 0;
- * });
- * // => [4, 6]
- *
- * var users = [
- * { 'user': 'barney', 'age': 36, 'active': true },
- * { 'user': 'fred', 'age': 40, 'active': false }
- * ];
+ * function Foo() {
+ * this.b = 2;
+ * }
*
- * // using the `_.matches` callback shorthand
- * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');
- * // => ['barney']
+ * Foo.prototype.c = 3;
*
- * // using the `_.matchesProperty` callback shorthand
- * _.pluck(_.filter(users, 'active', false), 'user');
- * // => ['fred']
+ * _.assign({ 'a': 1 }, new Foo);
+ * // => { 'a': 1, 'b': 2 }
*
- * // using the `_.property` callback shorthand
- * _.pluck(_.filter(users, 'active'), 'user');
- * // => ['barney']
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
*/
- function filter(collection, predicate, thisArg) {
- var func = isArray(collection) ? arrayFilter : baseFilter;
- predicate = getCallback(predicate, thisArg, 3);
- return func(collection, predicate);
+ function toPlainObject(value) {
+ return baseCopy(value, keysIn(value));
}
/**
- * Iterates over elements of `collection`, returning the first element
- * `predicate` returns truthy for. The predicate is bound to `thisArg` and
- * invoked with three arguments: (value, index|key, collection).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
+ * Assigns own enumerable properties of source object(s) to the destination
+ * object. Subsequent sources overwrite property assignments of previous sources.
+ * If `customizer` is provided it is invoked to produce the assigned values.
+ * The `customizer` is bound to `thisArg` and invoked with five arguments:
+ * (objectValue, sourceValue, key, object, source).
*
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * **Note:** This method mutates `object` and is based on
+ * [`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign).
*
* @static
* @memberOf _
- * @alias detect
- * @category Collection
- * @param {Array|Object|string} collection The collection to search.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {*} Returns the matched element, else `undefined`.
+ * @alias extend
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {Object} Returns `object`.
* @example
*
- * var users = [
- * { 'user': 'barney', 'age': 36, 'active': true },
- * { 'user': 'fred', 'age': 40, 'active': false },
- * { 'user': 'pebbles', 'age': 1, 'active': true }
- * ];
- *
- * _.result(_.find(users, function(chr) {
- * return chr.age < 40;
- * }), 'user');
- * // => 'barney'
- *
- * // using the `_.matches` callback shorthand
- * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');
- * // => 'pebbles'
+ * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' });
+ * // => { 'user': 'fred', 'age': 40 }
*
- * // using the `_.matchesProperty` callback shorthand
- * _.result(_.find(users, 'active', false), 'user');
- * // => 'fred'
+ * // using a customizer callback
+ * var defaults = _.partialRight(_.assign, function(value, other) {
+ * return _.isUndefined(value) ? other : value;
+ * });
*
- * // using the `_.property` callback shorthand
- * _.result(_.find(users, 'active'), 'user');
- * // => 'barney'
+ * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
+ * // => { 'user': 'barney', 'age': 36 }
*/
- var find = createFind(baseEach);
+ var assign = createAssigner(function(object, source, customizer) {
+ return customizer
+ ? assignWith(object, source, customizer)
+ : baseAssign(object, source);
+ });
/**
- * This method is like `_.find` except that it iterates over elements of
- * `collection` from right to left.
+ * Creates an object that inherits from the given `prototype` object. If a
+ * `properties` object is provided its own enumerable properties are assigned
+ * to the created object.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to search.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {*} Returns the matched element, else `undefined`.
+ * @category Object
+ * @param {Object} prototype The object to inherit from.
+ * @param {Object} [properties] The properties to assign to the object.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Object} Returns the new object.
* @example
*
- * _.findLast([1, 2, 3, 4], function(n) {
- * return n % 2 == 1;
+ * function Shape() {
+ * this.x = 0;
+ * this.y = 0;
+ * }
+ *
+ * function Circle() {
+ * Shape.call(this);
+ * }
+ *
+ * Circle.prototype = _.create(Shape.prototype, {
+ * 'constructor': Circle
* });
- * // => 3
+ *
+ * var circle = new Circle;
+ * circle instanceof Circle;
+ * // => true
+ *
+ * circle instanceof Shape;
+ * // => true
*/
- var findLast = createFind(baseEachRight, true);
+ function create(prototype, properties, guard) {
+ var result = baseCreate(prototype);
+ if (guard && isIterateeCall(prototype, properties, guard)) {
+ properties = null;
+ }
+ return properties ? baseAssign(result, properties) : result;
+ }
/**
- * Performs a deep comparison between each element in `collection` and the
- * source object, returning the first element that has equivalent property
- * values.
+ * Assigns own enumerable properties of source object(s) to the destination
+ * object for all destination properties that resolve to `undefined`. Once a
+ * property is set, additional values of the same property are ignored.
*
- * **Note:** This method supports comparing arrays, booleans, `Date` objects,
- * numbers, `Object` objects, regexes, and strings. Objects are compared by
- * their own, not inherited, enumerable properties. For comparing a single
- * own or inherited property value see `_.matchesProperty`.
+ * **Note:** This method mutates `object`.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to search.
- * @param {Object} source The object of property values to match.
- * @returns {*} Returns the matched element, else `undefined`.
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
* @example
*
- * var users = [
- * { 'user': 'barney', 'age': 36, 'active': true },
- * { 'user': 'fred', 'age': 40, 'active': false }
- * ];
- *
- * _.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user');
- * // => 'barney'
- *
- * _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user');
- * // => 'fred'
+ * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
+ * // => { 'user': 'barney', 'age': 36 }
*/
- function findWhere(collection, source) {
- return find(collection, baseMatches(source));
- }
+ var defaults = restParam(function(args) {
+ var object = args[0];
+ if (object == null) {
+ return object;
+ }
+ args.push(assignDefaults);
+ return assign.apply(undefined, args);
+ });
/**
- * Iterates over elements of `collection` invoking `iteratee` for each element.
- * The `iteratee` is bound to `thisArg` and invoked with three arguments:
- * (value, index|key, collection). Iteratee functions may exit iteration early
- * by explicitly returning `false`.
+ * This method is like `_.find` except that it returns the key of the first
+ * element `predicate` returns truthy for instead of the element itself.
*
- * **Note:** As with other "Collections" methods, objects with a "length" property
- * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
- * may be used for object iteration.
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
*
* @static
* @memberOf _
- * @alias each
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} [iteratee=_.identity] The function invoked per iteration.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {Array|Object|string} Returns `collection`.
+ * @category Object
+ * @param {Object} object The object to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
* @example
*
- * _([1, 2]).forEach(function(n) {
- * console.log(n);
- * }).value();
- * // => logs each value from left to right and returns the array
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
*
- * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
- * console.log(n, key);
+ * _.findKey(users, function(chr) {
+ * return chr.age < 40;
* });
- * // => logs each value-key pair and returns the object (iteration order is not guaranteed)
- */
- var forEach = createForEach(arrayEach, baseEach);
-
- /**
- * This method is like `_.forEach` except that it iterates over elements of
- * `collection` from right to left.
+ * // => 'barney' (iteration order is not guaranteed)
*
- * @static
- * @memberOf _
- * @alias eachRight
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} [iteratee=_.identity] The function invoked per iteration.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {Array|Object|string} Returns `collection`.
- * @example
+ * // using the `_.matches` callback shorthand
+ * _.findKey(users, { 'age': 1, 'active': true });
+ * // => 'pebbles'
*
- * _([1, 2]).forEachRight(function(n) {
- * console.log(n);
- * }).value();
- * // => logs each value from right to left and returns the array
+ * // using the `_.matchesProperty` callback shorthand
+ * _.findKey(users, 'active', false);
+ * // => 'fred'
+ *
+ * // using the `_.property` callback shorthand
+ * _.findKey(users, 'active');
+ * // => 'barney'
*/
- var forEachRight = createForEach(arrayEachRight, baseEachRight);
+ var findKey = createFindKey(baseForOwn);
/**
- * Creates an object composed of keys generated from the results of running
- * each element of `collection` through `iteratee`. The corresponding value
- * of each key is an array of the elements responsible for generating the key.
- * The `iteratee` is bound to `thisArg` and invoked with three arguments:
- * (value, index|key, collection).
+ * This method is like `_.findKey` except that it iterates over elements of
+ * a collection in the opposite order.
*
- * If a property name is provided for `iteratee` the created `_.property`
+ * If a property name is provided for `predicate` the created `_.property`
* style callback returns the property value of the given element.
*
* If a value is also provided for `thisArg` the created `_.matchesProperty`
* style callback returns `true` for elements that have a matching property
* value, else `false`.
*
- * If an object is provided for `iteratee` the created `_.matches` style
+ * If an object is provided for `predicate` the created `_.matches` style
* callback returns `true` for elements that have the properties of the given
* object, else `false`.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * @category Object
+ * @param {Object} object The object to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
* per iteration.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {Object} Returns the composed aggregate object.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
* @example
*
- * _.groupBy([4.2, 6.1, 6.4], function(n) {
- * return Math.floor(n);
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findLastKey(users, function(chr) {
+ * return chr.age < 40;
* });
- * // => { '4': [4.2], '6': [6.1, 6.4] }
+ * // => returns `pebbles` assuming `_.findKey` returns `barney`
*
- * _.groupBy([4.2, 6.1, 6.4], function(n) {
- * return this.floor(n);
- * }, Math);
- * // => { '4': [4.2], '6': [6.1, 6.4] }
+ * // using the `_.matches` callback shorthand
+ * _.findLastKey(users, { 'age': 36, 'active': true });
+ * // => 'barney'
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.findLastKey(users, 'active', false);
+ * // => 'fred'
*
* // using the `_.property` callback shorthand
- * _.groupBy(['one', 'two', 'three'], 'length');
- * // => { '3': ['one', 'two'], '5': ['three'] }
+ * _.findLastKey(users, 'active');
+ * // => 'pebbles'
*/
- var groupBy = createAggregator(function(result, value, key) {
- if (hasOwnProperty.call(result, key)) {
- result[key].push(value);
- } else {
- result[key] = [value];
- }
- });
+ var findLastKey = createFindKey(baseForOwnRight);
/**
- * Checks if `value` is in `collection` using `SameValueZero` for equality
- * comparisons. If `fromIndex` is negative, it is used as the offset from
- * the end of `collection`.
- *
- * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
- * comparisons are like strict equality comparisons, e.g. `===`, except that
- * `NaN` matches `NaN`.
+ * Iterates over own and inherited enumerable properties of an object invoking
+ * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked
+ * with three arguments: (value, key, object). Iteratee functions may exit
+ * iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
- * @alias contains, include
- * @category Collection
- * @param {Array|Object|string} collection The collection to search.
- * @param {*} target The value to search for.
- * @param {number} [fromIndex=0] The index to search from.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
- * @returns {boolean} Returns `true` if a matching element is found, else `false`.
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns `object`.
* @example
*
- * _.includes([1, 2, 3], 1);
- * // => true
- *
- * _.includes([1, 2, 3], 1, 2);
- * // => false
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
*
- * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
- * // => true
+ * Foo.prototype.c = 3;
*
- * _.includes('pebbles', 'eb');
- * // => true
+ * _.forIn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed)
*/
- function includes(collection, target, fromIndex, guard) {
- var length = collection ? getLength(collection) : 0;
- if (!isLength(length)) {
- collection = values(collection);
- length = collection.length;
- }
- if (!length) {
- return false;
- }
- if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
- fromIndex = 0;
- } else {
- fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
- }
- return (typeof collection == 'string' || !isArray(collection) && isString(collection))
- ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1)
- : (getIndexOf(collection, target, fromIndex) > -1);
- }
+ var forIn = createForIn(baseFor);
/**
- * Creates an object composed of keys generated from the results of running
- * each element of `collection` through `iteratee`. The corresponding value
- * of each key is the last element responsible for generating the key. The
- * iteratee function is bound to `thisArg` and invoked with three arguments:
- * (value, index|key, collection).
- *
- * If a property name is provided for `iteratee` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `iteratee` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * This method is like `_.forIn` except that it iterates over properties of
+ * `object` in the opposite order.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [iteratee=_.identity] The function invoked
- * per iteration.
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {Object} Returns the composed aggregate object.
+ * @returns {Object} Returns `object`.
* @example
*
- * var keyData = [
- * { 'dir': 'left', 'code': 97 },
- * { 'dir': 'right', 'code': 100 }
- * ];
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
*
- * _.indexBy(keyData, 'dir');
- * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+ * Foo.prototype.c = 3;
*
- * _.indexBy(keyData, function(object) {
- * return String.fromCharCode(object.code);
+ * _.forInRight(new Foo, function(value, key) {
+ * console.log(key);
* });
- * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
- *
- * _.indexBy(keyData, function(object) {
- * return this.fromCharCode(object.code);
- * }, String);
- * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+ * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c'
*/
- var indexBy = createAggregator(function(result, value, key) {
- result[key] = value;
- });
+ var forInRight = createForIn(baseForRight);
/**
- * Invokes the method at `path` on each element in `collection`, returning
- * an array of the results of each invoked method. Any additional arguments
- * are provided to each invoked method. If `methodName` is a function it is
- * invoked for, and `this` bound to, each element in `collection`.
+ * Iterates over own enumerable properties of an object invoking `iteratee`
+ * for each property. The `iteratee` is bound to `thisArg` and invoked with
+ * three arguments: (value, key, object). Iteratee functions may exit iteration
+ * early by explicitly returning `false`.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Array|Function|string} path The path of the method to invoke or
- * the function invoked per iteration.
- * @param {...*} [args] The arguments to invoke the method with.
- * @returns {Array} Returns the array of results.
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns `object`.
* @example
*
- * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
- * // => [[1, 5, 7], [1, 2, 3]]
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
*
- * _.invoke([123, 456], String.prototype.split, '');
- * // => [['1', '2', '3'], ['4', '5', '6']]
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'a' and 'b' (iteration order is not guaranteed)
*/
- var invoke = restParam(function(collection, path, args) {
- var index = -1,
- isFunc = typeof path == 'function',
- isProp = isKey(path),
- length = getLength(collection),
- result = isLength(length) ? Array(length) : [];
-
- baseEach(collection, function(value) {
- var func = isFunc ? path : (isProp && value != null && value[path]);
- result[++index] = func ? func.apply(value, args) : invokePath(value, path, args);
- });
- return result;
- });
+ var forOwn = createForOwn(baseForOwn);
/**
- * Creates an array of values by running each element in `collection` through
- * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three
- * arguments: (value, index|key, collection).
- *
- * If a property name is provided for `iteratee` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `iteratee` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
- *
- * Many lodash methods are guarded to work as interatees for methods like
- * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
- *
- * The guarded methods are:
- * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, `drop`,
- * `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`, `parseInt`,
- * `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimLeft`,
- * `trimRight`, `trunc`, `random`, `range`, `sample`, `some`, `uniq`, and `words`
+ * This method is like `_.forOwn` except that it iterates over properties of
+ * `object` in the opposite order.
*
* @static
* @memberOf _
- * @alias collect
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [iteratee=_.identity] The function invoked
- * per iteration.
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {Array} Returns the new mapped array.
+ * @returns {Object} Returns `object`.
* @example
*
- * function timesThree(n) {
- * return n * 3;
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
* }
*
- * _.map([1, 2], timesThree);
- * // => [3, 6]
+ * Foo.prototype.c = 3;
*
- * _.map({ 'a': 1, 'b': 2 }, timesThree);
- * // => [3, 6] (iteration order is not guaranteed)
+ * _.forOwnRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b'
+ */
+ var forOwnRight = createForOwn(baseForOwnRight);
+
+ /**
+ * Creates an array of function property names from all enumerable properties,
+ * own and inherited, of `object`.
*
- * var users = [
- * { 'user': 'barney' },
- * { 'user': 'fred' }
- * ];
+ * @static
+ * @memberOf _
+ * @alias methods
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns the new array of property names.
+ * @example
*
- * // using the `_.property` callback shorthand
- * _.map(users, 'user');
- * // => ['barney', 'fred']
+ * _.functions(_);
+ * // => ['after', 'ary', 'assign', ...]
*/
- function map(collection, iteratee, thisArg) {
- var func = isArray(collection) ? arrayMap : baseMap;
- iteratee = getCallback(iteratee, thisArg, 3);
- return func(collection, iteratee);
+ function functions(object) {
+ return baseFunctions(object, keysIn(object));
}
/**
- * Creates an array of elements split into two groups, the first of which
- * contains elements `predicate` returns truthy for, while the second of which
- * contains elements `predicate` returns falsey for. The predicate is bound
- * to `thisArg` and invoked with three arguments: (value, index|key, collection).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * Gets the property value of `path` on `object`. If the resolved value is
+ * `undefined` the `defaultValue` is used in its place.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the array of grouped elements.
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
+ * @returns {*} Returns the resolved value.
* @example
*
- * _.partition([1, 2, 3], function(n) {
- * return n % 2;
- * });
- * // => [[1, 3], [2]]
- *
- * _.partition([1.2, 2.3, 3.4], function(n) {
- * return this.floor(n) % 2;
- * }, Math);
- * // => [[1.2, 3.4], [2.3]]
- *
- * var users = [
- * { 'user': 'barney', 'age': 36, 'active': false },
- * { 'user': 'fred', 'age': 40, 'active': true },
- * { 'user': 'pebbles', 'age': 1, 'active': false }
- * ];
- *
- * var mapper = function(array) {
- * return _.pluck(array, 'user');
- * };
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
*
- * // using the `_.matches` callback shorthand
- * _.map(_.partition(users, { 'age': 1, 'active': false }), mapper);
- * // => [['pebbles'], ['barney', 'fred']]
+ * _.get(object, 'a[0].b.c');
+ * // => 3
*
- * // using the `_.matchesProperty` callback shorthand
- * _.map(_.partition(users, 'active', false), mapper);
- * // => [['barney', 'pebbles'], ['fred']]
+ * _.get(object, ['a', '0', 'b', 'c']);
+ * // => 3
*
- * // using the `_.property` callback shorthand
- * _.map(_.partition(users, 'active'), mapper);
- * // => [['fred'], ['barney', 'pebbles']]
+ * _.get(object, 'a.b.c', 'default');
+ * // => 'default'
*/
- var partition = createAggregator(function(result, value, key) {
- result[key ? 0 : 1].push(value);
- }, function() { return [[], []]; });
+ function get(object, path, defaultValue) {
+ var result = object == null ? undefined : baseGet(object, toPath(path), path + '');
+ return result === undefined ? defaultValue : result;
+ }
/**
- * Gets the property value of `path` from all elements in `collection`.
+ * Checks if `path` is a direct property.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Array|string} path The path of the property to pluck.
- * @returns {Array} Returns the property values.
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` is a direct property, else `false`.
* @example
*
- * var users = [
- * { 'user': 'barney', 'age': 36 },
- * { 'user': 'fred', 'age': 40 }
- * ];
+ * var object = { 'a': { 'b': { 'c': 3 } } };
*
- * _.pluck(users, 'user');
- * // => ['barney', 'fred']
+ * _.has(object, 'a');
+ * // => true
*
- * var userIndex = _.indexBy(users, 'user');
- * _.pluck(userIndex, 'age');
- * // => [36, 40] (iteration order is not guaranteed)
+ * _.has(object, 'a.b.c');
+ * // => true
+ *
+ * _.has(object, ['a', 'b', 'c']);
+ * // => true
*/
- function pluck(collection, path) {
- return map(collection, property(path));
+ function has(object, path) {
+ if (object == null) {
+ return false;
+ }
+ var result = hasOwnProperty.call(object, path);
+ if (!result && !isKey(path)) {
+ path = toPath(path);
+ object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+ path = last(path);
+ result = object != null && hasOwnProperty.call(object, path);
+ }
+ return result;
}
/**
- * Reduces `collection` to a value which is the accumulated result of running
- * each element in `collection` through `iteratee`, where each successive
- * invocation is supplied the return value of the previous. If `accumulator`
- * is not provided the first element of `collection` is used as the initial
- * value. The `iteratee` is bound to `thisArg` and invoked with four arguments:
- * (accumulator, value, index|key, collection).
- *
- * Many lodash methods are guarded to work as interatees for methods like
- * `_.reduce`, `_.reduceRight`, and `_.transform`.
- *
- * The guarded methods are:
- * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder`
+ * Creates an object composed of the inverted keys and values of `object`.
+ * If `object` contains duplicate values, subsequent values overwrite property
+ * assignments of previous values unless `multiValue` is `true`.
*
* @static
* @memberOf _
- * @alias foldl, inject
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} [iteratee=_.identity] The function invoked per iteration.
- * @param {*} [accumulator] The initial value.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {*} Returns the accumulated value.
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @param {boolean} [multiValue] Allow multiple values per key.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Object} Returns the new inverted object.
* @example
*
- * _.reduce([1, 2], function(total, n) {
- * return total + n;
- * });
- * // => 3
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
*
- * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {
- * result[key] = n * 3;
- * return result;
- * }, {});
- * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed)
+ * _.invert(object);
+ * // => { '1': 'c', '2': 'b' }
+ *
+ * // with `multiValue`
+ * _.invert(object, true);
+ * // => { '1': ['a', 'c'], '2': ['b'] }
*/
- var reduce = createReduce(arrayReduce, baseEach);
+ function invert(object, multiValue, guard) {
+ if (guard && isIterateeCall(object, multiValue, guard)) {
+ multiValue = null;
+ }
+ var index = -1,
+ props = keys(object),
+ length = props.length,
+ result = {};
+
+ while (++index < length) {
+ var key = props[index],
+ value = object[key];
+
+ if (multiValue) {
+ if (hasOwnProperty.call(result, value)) {
+ result[value].push(key);
+ } else {
+ result[value] = [key];
+ }
+ }
+ else {
+ result[value] = key;
+ }
+ }
+ return result;
+ }
/**
- * This method is like `_.reduce` except that it iterates over elements of
- * `collection` from right to left.
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys)
+ * for more details.
*
* @static
* @memberOf _
- * @alias foldr
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} [iteratee=_.identity] The function invoked per iteration.
- * @param {*} [accumulator] The initial value.
- * @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {*} Returns the accumulated value.
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
* @example
*
- * var array = [[0, 1], [2, 3], [4, 5]];
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
*
- * _.reduceRight(array, function(flattened, other) {
- * return flattened.concat(other);
- * }, []);
- * // => [4, 5, 2, 3, 0, 1]
+ * Foo.prototype.c = 3;
+ *
+ * _.keys(new Foo);
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * _.keys('hi');
+ * // => ['0', '1']
*/
- var reduceRight = createReduce(arrayReduceRight, baseEachRight);
+ var keys = !nativeKeys ? shimKeys : function(object) {
+ var Ctor = object != null && object.constructor;
+ if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
+ (typeof object != 'function' && isArrayLike(object))) {
+ return shimKeys(object);
+ }
+ return isObject(object) ? nativeKeys(object) : [];
+ };
/**
- * The opposite of `_.filter`; this method returns the elements of `collection`
- * that `predicate` does **not** return truthy for.
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
+ * Creates an array of the own and inherited enumerable property names of `object`.
*
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * **Note:** Non-object values are coerced to objects.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
- * per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {Array} Returns the new filtered array.
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
* @example
*
- * _.reject([1, 2, 3, 4], function(n) {
- * return n % 2 == 0;
- * });
- * // => [1, 3]
- *
- * var users = [
- * { 'user': 'barney', 'age': 36, 'active': false },
- * { 'user': 'fred', 'age': 40, 'active': true }
- * ];
- *
- * // using the `_.matches` callback shorthand
- * _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user');
- * // => ['barney']
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
*
- * // using the `_.matchesProperty` callback shorthand
- * _.pluck(_.reject(users, 'active', false), 'user');
- * // => ['fred']
+ * Foo.prototype.c = 3;
*
- * // using the `_.property` callback shorthand
- * _.pluck(_.reject(users, 'active'), 'user');
- * // => ['barney']
+ * _.keysIn(new Foo);
+ * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
*/
- function reject(collection, predicate, thisArg) {
- var func = isArray(collection) ? arrayFilter : baseFilter;
- predicate = getCallback(predicate, thisArg, 3);
- return func(collection, function(value, index, collection) {
- return !predicate(value, index, collection);
- });
- }
-
- /**
- * Gets a random element or `n` random elements from a collection.
- *
- * @static
- * @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to sample.
- * @param {number} [n] The number of elements to sample.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {*} Returns the random sample(s).
- * @example
- *
- * _.sample([1, 2, 3, 4]);
- * // => 2
- *
- * _.sample([1, 2, 3, 4], 2);
- * // => [3, 1]
- */
- function sample(collection, n, guard) {
- if (guard ? isIterateeCall(collection, n, guard) : n == null) {
- collection = toIterable(collection);
- var length = collection.length;
- return length > 0 ? collection[baseRandom(0, length - 1)] : undefined;
+ function keysIn(object) {
+ if (object == null) {
+ return [];
}
- var result = shuffle(collection);
- result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length);
- return result;
- }
-
- /**
- * Creates an array of shuffled values, using a version of the
- * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
- *
- * @static
- * @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to shuffle.
- * @returns {Array} Returns the new shuffled array.
- * @example
- *
- * _.shuffle([1, 2, 3, 4]);
- * // => [4, 1, 3, 2]
- */
- function shuffle(collection) {
- collection = toIterable(collection);
+ if (!isObject(object)) {
+ object = Object(object);
+ }
+ var length = object.length;
+ length = (length && isLength(length) &&
+ (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0;
- var index = -1,
- length = collection.length,
- result = Array(length);
+ var Ctor = object.constructor,
+ index = -1,
+ isProto = typeof Ctor == 'function' && Ctor.prototype === object,
+ result = Array(length),
+ skipIndexes = length > 0;
while (++index < length) {
- var rand = baseRandom(0, index);
- if (index != rand) {
- result[index] = result[rand];
+ result[index] = (index + '');
+ }
+ for (var key in object) {
+ if (!(skipIndexes && isIndex(key, length)) &&
+ !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
+ result.push(key);
}
- result[rand] = collection[index];
}
return result;
}
/**
- * Gets the size of `collection` by returning its length for array-like
- * values or the number of own enumerable properties for objects.
- *
- * @static
- * @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to inspect.
- * @returns {number} Returns the size of `collection`.
- * @example
- *
- * _.size([1, 2, 3]);
- * // => 3
- *
- * _.size({ 'a': 1, 'b': 2 });
- * // => 2
- *
- * _.size('pebbles');
- * // => 7
- */
- function size(collection) {
- var length = collection ? getLength(collection) : 0;
- return isLength(length) ? length : keys(collection).length;
- }
-
- /**
- * Checks if `predicate` returns truthy for **any** element of `collection`.
- * The function returns as soon as it finds a passing value and does not iterate
- * over the entire collection. The predicate is bound to `thisArg` and invoked
- * with three arguments: (value, index|key, collection).
- *
- * If a property name is provided for `predicate` the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If a value is also provided for `thisArg` the created `_.matchesProperty`
- * style callback returns `true` for elements that have a matching property
- * value, else `false`.
- *
- * If an object is provided for `predicate` the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * The opposite of `_.mapValues`; this method creates an object with the
+ * same values as `object` and keys generated by running each own enumerable
+ * property of `object` through `iteratee`.
*
* @static
* @memberOf _
- * @alias any
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
* per iteration.
- * @param {*} [thisArg] The `this` binding of `predicate`.
- * @returns {boolean} Returns `true` if any element passes the predicate check,
- * else `false`.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the new mapped object.
* @example
*
- * _.some([null, 0, 'yes', false], Boolean);
- * // => true
- *
- * var users = [
- * { 'user': 'barney', 'active': true },
- * { 'user': 'fred', 'active': false }
- * ];
- *
- * // using the `_.matches` callback shorthand
- * _.some(users, { 'user': 'barney', 'active': false });
- * // => false
- *
- * // using the `_.matchesProperty` callback shorthand
- * _.some(users, 'active', false);
- * // => true
- *
- * // using the `_.property` callback shorthand
- * _.some(users, 'active');
- * // => true
+ * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
+ * return key + value;
+ * });
+ * // => { 'a1': 1, 'b2': 2 }
*/
- function some(collection, predicate, thisArg) {
- var func = isArray(collection) ? arraySome : baseSome;
- if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
- predicate = null;
- }
- if (typeof predicate != 'function' || thisArg !== undefined) {
- predicate = getCallback(predicate, thisArg, 3);
- }
- return func(collection, predicate);
- }
+ var mapKeys = createObjectMapper(true);
/**
- * Creates an array of elements, sorted in ascending order by the results of
- * running each element in a collection through `iteratee`. This method performs
- * a stable sort, that is, it preserves the original sort order of equal elements.
- * The `iteratee` is bound to `thisArg` and invoked with three arguments:
- * (value, index|key, collection).
+ * Creates an object with the same keys as `object` and values generated by
+ * running each own enumerable property of `object` through `iteratee`. The
+ * iteratee function is bound to `thisArg` and invoked with three arguments:
+ * (value, key, object).
*
* If a property name is provided for `iteratee` the created `_.property`
* style callback returns the property value of the given element.
@@ -12996,23527 +12797,5482 @@ var Grommet =
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
+ * @category Object
+ * @param {Object} object The object to iterate over.
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
* per iteration.
* @param {*} [thisArg] The `this` binding of `iteratee`.
- * @returns {Array} Returns the new sorted array.
+ * @returns {Object} Returns the new mapped object.
* @example
*
- * _.sortBy([1, 2, 3], function(n) {
- * return Math.sin(n);
+ * _.mapValues({ 'a': 1, 'b': 2 }, function(n) {
+ * return n * 3;
* });
- * // => [3, 1, 2]
- *
- * _.sortBy([1, 2, 3], function(n) {
- * return this.sin(n);
- * }, Math);
- * // => [3, 1, 2]
+ * // => { 'a': 3, 'b': 6 }
*
- * var users = [
- * { 'user': 'fred' },
- * { 'user': 'pebbles' },
- * { 'user': 'barney' }
- * ];
+ * var users = {
+ * 'fred': { 'user': 'fred', 'age': 40 },
+ * 'pebbles': { 'user': 'pebbles', 'age': 1 }
+ * };
*
* // using the `_.property` callback shorthand
- * _.pluck(_.sortBy(users, 'user'), 'user');
- * // => ['barney', 'fred', 'pebbles']
+ * _.mapValues(users, 'age');
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
*/
- function sortBy(collection, iteratee, thisArg) {
- if (collection == null) {
- return [];
- }
- if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
- iteratee = null;
- }
- var index = -1;
- iteratee = getCallback(iteratee, thisArg, 3);
-
- var result = baseMap(collection, function(value, key, collection) {
- return { 'criteria': iteratee(value, key, collection), 'index': ++index, 'value': value };
- });
- return baseSortBy(result, compareAscending);
- }
+ var mapValues = createObjectMapper();
/**
- * This method is like `_.sortBy` except that it can sort by multiple iteratees
- * or property names.
- *
- * If a property name is provided for an iteratee the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If an object is provided for an iteratee the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * Recursively merges own enumerable properties of the source object(s), that
+ * don't resolve to `undefined` into the destination object. Subsequent sources
+ * overwrite property assignments of previous sources. If `customizer` is
+ * provided it is invoked to produce the merged values of the destination and
+ * source properties. If `customizer` returns `undefined` merging is handled
+ * by the method instead. The `customizer` is bound to `thisArg` and invoked
+ * with five arguments: (objectValue, sourceValue, key, object, source).
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {...(Function|Function[]|Object|Object[]|string|string[])} iteratees
- * The iteratees to sort by, specified as individual values or arrays of values.
- * @returns {Array} Returns the new sorted array.
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {Object} Returns `object`.
* @example
*
- * var users = [
- * { 'user': 'fred', 'age': 48 },
- * { 'user': 'barney', 'age': 36 },
- * { 'user': 'fred', 'age': 42 },
- * { 'user': 'barney', 'age': 34 }
- * ];
+ * var users = {
+ * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
+ * };
*
- * _.map(_.sortByAll(users, ['user', 'age']), _.values);
- * // => [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]
+ * var ages = {
+ * 'data': [{ 'age': 36 }, { 'age': 40 }]
+ * };
*
- * _.map(_.sortByAll(users, 'user', function(chr) {
- * return Math.floor(chr.age / 10);
- * }), _.values);
- * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
- */
- var sortByAll = restParam(function(collection, iteratees) {
- if (collection == null) {
- return [];
- }
- var guard = iteratees[2];
- if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) {
- iteratees.length = 1;
- }
- return baseSortByOrder(collection, baseFlatten(iteratees), []);
- });
-
- /**
- * This method is like `_.sortByAll` except that it allows specifying the
- * sort orders of the iteratees to sort by. A truthy value in `orders` will
- * sort the corresponding property name in ascending order while a falsey
- * value will sort it in descending order.
- *
- * If a property name is provided for an iteratee the created `_.property`
- * style callback returns the property value of the given element.
- *
- * If an object is provided for an iteratee the created `_.matches` style
- * callback returns `true` for elements that have the properties of the given
- * object, else `false`.
+ * _.merge(users, ages);
+ * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
*
- * @static
- * @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
- * @param {boolean[]} orders The sort orders of `iteratees`.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
- * @returns {Array} Returns the new sorted array.
- * @example
+ * // using a customizer callback
+ * var object = {
+ * 'fruits': ['apple'],
+ * 'vegetables': ['beet']
+ * };
*
- * var users = [
- * { 'user': 'fred', 'age': 48 },
- * { 'user': 'barney', 'age': 34 },
- * { 'user': 'fred', 'age': 42 },
- * { 'user': 'barney', 'age': 36 }
- * ];
+ * var other = {
+ * 'fruits': ['banana'],
+ * 'vegetables': ['carrot']
+ * };
*
- * // sort by `user` in ascending order and by `age` in descending order
- * _.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values);
- * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
+ * _.merge(object, other, function(a, b) {
+ * if (_.isArray(a)) {
+ * return a.concat(b);
+ * }
+ * });
+ * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
*/
- function sortByOrder(collection, iteratees, orders, guard) {
- if (collection == null) {
- return [];
- }
- if (guard && isIterateeCall(iteratees, orders, guard)) {
- orders = null;
- }
- if (!isArray(iteratees)) {
- iteratees = iteratees == null ? [] : [iteratees];
- }
- if (!isArray(orders)) {
- orders = orders == null ? [] : [orders];
- }
- return baseSortByOrder(collection, iteratees, orders);
- }
+ var merge = createAssigner(baseMerge);
/**
- * Performs a deep comparison between each element in `collection` and the
- * source object, returning an array of all elements that have equivalent
- * property values.
- *
- * **Note:** This method supports comparing arrays, booleans, `Date` objects,
- * numbers, `Object` objects, regexes, and strings. Objects are compared by
- * their own, not inherited, enumerable properties. For comparing a single
- * own or inherited property value see `_.matchesProperty`.
+ * The opposite of `_.pick`; this method creates an object composed of the
+ * own and inherited enumerable properties of `object` that are not omitted.
*
* @static
* @memberOf _
- * @category Collection
- * @param {Array|Object|string} collection The collection to search.
- * @param {Object} source The object of property values to match.
- * @returns {Array} Returns the new filtered array.
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function|...(string|string[])} [predicate] The function invoked per
+ * iteration or property names to omit, specified as individual property
+ * names or arrays of property names.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Object} Returns the new object.
* @example
*
- * var users = [
- * { 'user': 'barney', 'age': 36, 'active': false, 'pets': ['hoppy'] },
- * { 'user': 'fred', 'age': 40, 'active': true, 'pets': ['baby puss', 'dino'] }
- * ];
+ * var object = { 'user': 'fred', 'age': 40 };
*
- * _.pluck(_.where(users, { 'age': 36, 'active': false }), 'user');
- * // => ['barney']
+ * _.omit(object, 'age');
+ * // => { 'user': 'fred' }
*
- * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user');
- * // => ['fred']
+ * _.omit(object, _.isNumber);
+ * // => { 'user': 'fred' }
*/
- function where(collection, source) {
- return filter(collection, baseMatches(source));
- }
-
- /*------------------------------------------------------------------------*/
+ var omit = restParam(function(object, props) {
+ if (object == null) {
+ return {};
+ }
+ if (typeof props[0] != 'function') {
+ var props = arrayMap(baseFlatten(props), String);
+ return pickByArray(object, baseDifference(keysIn(object), props));
+ }
+ var predicate = bindCallback(props[0], props[1], 3);
+ return pickByCallback(object, function(value, key, object) {
+ return !predicate(value, key, object);
+ });
+ });
/**
- * Gets the number of milliseconds that have elapsed since the Unix epoch
- * (1 January 1970 00:00:00 UTC).
+ * Creates a two dimensional array of the key-value pairs for `object`,
+ * e.g. `[[key1, value1], [key2, value2]]`.
*
* @static
* @memberOf _
- * @category Date
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the new array of key-value pairs.
* @example
*
- * _.defer(function(stamp) {
- * console.log(_.now() - stamp);
- * }, _.now());
- * // => logs the number of milliseconds it took for the deferred function to be invoked
+ * _.pairs({ 'barney': 36, 'fred': 40 });
+ * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)
*/
- var now = nativeNow || function() {
- return new Date().getTime();
- };
+ function pairs(object) {
+ var index = -1,
+ props = keys(object),
+ length = props.length,
+ result = Array(length);
- /*------------------------------------------------------------------------*/
+ while (++index < length) {
+ var key = props[index];
+ result[index] = [key, object[key]];
+ }
+ return result;
+ }
/**
- * The opposite of `_.before`; this method creates a function that invokes
- * `func` once it is called `n` or more times.
+ * Creates an object composed of the picked `object` properties. Property
+ * names may be specified as individual arguments or as arrays of property
+ * names. If `predicate` is provided it is invoked for each property of `object`
+ * picking the properties `predicate` returns truthy for. The predicate is
+ * bound to `thisArg` and invoked with three arguments: (value, key, object).
*
* @static
* @memberOf _
- * @category Function
- * @param {number} n The number of calls before `func` is invoked.
- * @param {Function} func The function to restrict.
- * @returns {Function} Returns the new restricted function.
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function|...(string|string[])} [predicate] The function invoked per
+ * iteration or property names to pick, specified as individual property
+ * names or arrays of property names.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Object} Returns the new object.
* @example
*
- * var saves = ['profile', 'settings'];
+ * var object = { 'user': 'fred', 'age': 40 };
*
- * var done = _.after(saves.length, function() {
- * console.log('done saving!');
- * });
+ * _.pick(object, 'user');
+ * // => { 'user': 'fred' }
*
- * _.forEach(saves, function(type) {
- * asyncSave({ 'type': type, 'complete': done });
- * });
- * // => logs 'done saving!' after the two async saves have completed
+ * _.pick(object, _.isString);
+ * // => { 'user': 'fred' }
*/
- function after(n, func) {
- if (typeof func != 'function') {
- if (typeof n == 'function') {
- var temp = n;
- n = func;
- func = temp;
- } else {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
+ var pick = restParam(function(object, props) {
+ if (object == null) {
+ return {};
}
- n = nativeIsFinite(n = +n) ? n : 0;
- return function() {
- if (--n < 1) {
- return func.apply(this, arguments);
- }
- };
- }
+ return typeof props[0] == 'function'
+ ? pickByCallback(object, bindCallback(props[0], props[1], 3))
+ : pickByArray(object, baseFlatten(props));
+ });
/**
- * Creates a function that accepts up to `n` arguments ignoring any
- * additional arguments.
+ * This method is like `_.get` except that if the resolved value is a function
+ * it is invoked with the `this` binding of its parent object and its result
+ * is returned.
*
* @static
* @memberOf _
- * @category Function
- * @param {Function} func The function to cap arguments for.
- * @param {number} [n=func.length] The arity cap.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Function} Returns the new function.
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to resolve.
+ * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
+ * @returns {*} Returns the resolved value.
* @example
*
- * _.map(['6', '8', '10'], _.ary(parseInt, 1));
- * // => [6, 8, 10]
+ * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
+ *
+ * _.result(object, 'a[0].b.c1');
+ * // => 3
+ *
+ * _.result(object, 'a[0].b.c2');
+ * // => 4
+ *
+ * _.result(object, 'a.b.c', 'default');
+ * // => 'default'
+ *
+ * _.result(object, 'a.b.c', _.constant('default'));
+ * // => 'default'
*/
- function ary(func, n, guard) {
- if (guard && isIterateeCall(func, n, guard)) {
- n = null;
+ function result(object, path, defaultValue) {
+ var result = object == null ? undefined : object[path];
+ if (result === undefined) {
+ if (object != null && !isKey(path, object)) {
+ path = toPath(path);
+ object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+ result = object == null ? undefined : object[last(path)];
+ }
+ result = result === undefined ? defaultValue : result;
}
- n = (func && n == null) ? func.length : nativeMax(+n || 0, 0);
- return createWrapper(func, ARY_FLAG, null, null, null, null, n);
+ return isFunction(result) ? result.call(object) : result;
}
/**
- * Creates a function that invokes `func`, with the `this` binding and arguments
- * of the created function, while it is called less than `n` times. Subsequent
- * calls to the created function return the result of the last `func` invocation.
+ * Sets the property value of `path` on `object`. If a portion of `path`
+ * does not exist it is created.
*
* @static
* @memberOf _
- * @category Function
- * @param {number} n The number of calls at which `func` is no longer invoked.
- * @param {Function} func The function to restrict.
- * @returns {Function} Returns the new restricted function.
- * @example
- *
- * jQuery('#add').on('click', _.before(5, addContactToList));
- * // => allows adding up to 4 contacts to the list
- */
- function before(n, func) {
- var result;
- if (typeof func != 'function') {
- if (typeof n == 'function') {
- var temp = n;
- n = func;
- func = temp;
- } else {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- }
- return function() {
- if (--n > 0) {
- result = func.apply(this, arguments);
- }
- if (n <= 1) {
- func = null;
- }
- return result;
- };
- }
-
- /**
- * Creates a function that invokes `func` with the `this` binding of `thisArg`
- * and prepends any additional `_.bind` arguments to those provided to the
- * bound function.
- *
- * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
- * may be used as a placeholder for partially applied arguments.
- *
- * **Note:** Unlike native `Function#bind` this method does not set the "length"
- * property of bound functions.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to bind.
- * @param {*} thisArg The `this` binding of `func`.
- * @param {...*} [partials] The arguments to be partially applied.
- * @returns {Function} Returns the new bound function.
- * @example
- *
- * var greet = function(greeting, punctuation) {
- * return greeting + ' ' + this.user + punctuation;
- * };
- *
- * var object = { 'user': 'fred' };
- *
- * var bound = _.bind(greet, object, 'hi');
- * bound('!');
- * // => 'hi fred!'
- *
- * // using placeholders
- * var bound = _.bind(greet, object, _, '!');
- * bound('hi');
- * // => 'hi fred!'
- */
- var bind = restParam(function(func, thisArg, partials) {
- var bitmask = BIND_FLAG;
- if (partials.length) {
- var holders = replaceHolders(partials, bind.placeholder);
- bitmask |= PARTIAL_FLAG;
- }
- return createWrapper(func, bitmask, thisArg, partials, holders);
- });
-
- /**
- * Binds methods of an object to the object itself, overwriting the existing
- * method. Method names may be specified as individual arguments or as arrays
- * of method names. If no method names are provided all enumerable function
- * properties, own and inherited, of `object` are bound.
- *
- * **Note:** This method does not set the "length" property of bound functions.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Object} object The object to bind and assign the bound methods to.
- * @param {...(string|string[])} [methodNames] The object method names to bind,
- * specified as individual method names or arrays of method names.
+ * @category Object
+ * @param {Object} object The object to augment.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
* @returns {Object} Returns `object`.
* @example
*
- * var view = {
- * 'label': 'docs',
- * 'onClick': function() {
- * console.log('clicked ' + this.label);
- * }
- * };
- *
- * _.bindAll(view);
- * jQuery('#docs').on('click', view.onClick);
- * // => logs 'clicked docs' when the element is clicked
- */
- var bindAll = restParam(function(object, methodNames) {
- methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object);
-
- var index = -1,
- length = methodNames.length;
-
- while (++index < length) {
- var key = methodNames[index];
- object[key] = createWrapper(object[key], BIND_FLAG, object);
- }
- return object;
- });
-
- /**
- * Creates a function that invokes the method at `object[key]` and prepends
- * any additional `_.bindKey` arguments to those provided to the bound function.
- *
- * This method differs from `_.bind` by allowing bound functions to reference
- * methods that may be redefined or don't yet exist.
- * See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
- * for more details.
- *
- * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
- * builds, may be used as a placeholder for partially applied arguments.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Object} object The object the method belongs to.
- * @param {string} key The key of the method.
- * @param {...*} [partials] The arguments to be partially applied.
- * @returns {Function} Returns the new bound function.
- * @example
- *
- * var object = {
- * 'user': 'fred',
- * 'greet': function(greeting, punctuation) {
- * return greeting + ' ' + this.user + punctuation;
- * }
- * };
- *
- * var bound = _.bindKey(object, 'greet', 'hi');
- * bound('!');
- * // => 'hi fred!'
- *
- * object.greet = function(greeting, punctuation) {
- * return greeting + 'ya ' + this.user + punctuation;
- * };
- *
- * bound('!');
- * // => 'hiya fred!'
- *
- * // using placeholders
- * var bound = _.bindKey(object, 'greet', _, '!');
- * bound('hi');
- * // => 'hiya fred!'
- */
- var bindKey = restParam(function(object, key, partials) {
- var bitmask = BIND_FLAG | BIND_KEY_FLAG;
- if (partials.length) {
- var holders = replaceHolders(partials, bindKey.placeholder);
- bitmask |= PARTIAL_FLAG;
- }
- return createWrapper(key, bitmask, object, partials, holders);
- });
-
- /**
- * Creates a function that accepts one or more arguments of `func` that when
- * called either invokes `func` returning its result, if all `func` arguments
- * have been provided, or returns a function that accepts one or more of the
- * remaining `func` arguments, and so on. The arity of `func` may be specified
- * if `func.length` is not sufficient.
- *
- * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
- * may be used as a placeholder for provided arguments.
- *
- * **Note:** This method does not set the "length" property of curried functions.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to curry.
- * @param {number} [arity=func.length] The arity of `func`.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Function} Returns the new curried function.
- * @example
- *
- * var abc = function(a, b, c) {
- * return [a, b, c];
- * };
- *
- * var curried = _.curry(abc);
- *
- * curried(1)(2)(3);
- * // => [1, 2, 3]
- *
- * curried(1, 2)(3);
- * // => [1, 2, 3]
- *
- * curried(1, 2, 3);
- * // => [1, 2, 3]
- *
- * // using placeholders
- * curried(1)(_, 3)(2);
- * // => [1, 2, 3]
- */
- var curry = createCurry(CURRY_FLAG);
-
- /**
- * This method is like `_.curry` except that arguments are applied to `func`
- * in the manner of `_.partialRight` instead of `_.partial`.
- *
- * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
- * builds, may be used as a placeholder for provided arguments.
- *
- * **Note:** This method does not set the "length" property of curried functions.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to curry.
- * @param {number} [arity=func.length] The arity of `func`.
- * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
- * @returns {Function} Returns the new curried function.
- * @example
- *
- * var abc = function(a, b, c) {
- * return [a, b, c];
- * };
- *
- * var curried = _.curryRight(abc);
- *
- * curried(3)(2)(1);
- * // => [1, 2, 3]
- *
- * curried(2, 3)(1);
- * // => [1, 2, 3]
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
*
- * curried(1, 2, 3);
- * // => [1, 2, 3]
+ * _.set(object, 'a[0].b.c', 4);
+ * console.log(object.a[0].b.c);
+ * // => 4
*
- * // using placeholders
- * curried(3)(1, _)(2);
- * // => [1, 2, 3]
+ * _.set(object, 'x[0].y.z', 5);
+ * console.log(object.x[0].y.z);
+ * // => 5
*/
- var curryRight = createCurry(CURRY_RIGHT_FLAG);
-
- /**
- * Creates a function that delays invoking `func` until after `wait` milliseconds
- * have elapsed since the last time it was invoked. The created function comes
- * with a `cancel` method to cancel delayed invocations. Provide an options
- * object to indicate that `func` should be invoked on the leading and/or
- * trailing edge of the `wait` timeout. Subsequent calls to the debounced
- * function return the result of the last `func` invocation.
- *
- * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
- * on the trailing edge of the timeout only if the the debounced function is
- * invoked more than once during the `wait` timeout.
- *
- * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
- * for details over the differences between `_.debounce` and `_.throttle`.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to debounce.
- * @param {number} [wait=0] The number of milliseconds to delay.
- * @param {Object} [options] The options object.
- * @param {boolean} [options.leading=false] Specify invoking on the leading
- * edge of the timeout.
- * @param {number} [options.maxWait] The maximum time `func` is allowed to be
- * delayed before it is invoked.
- * @param {boolean} [options.trailing=true] Specify invoking on the trailing
- * edge of the timeout.
- * @returns {Function} Returns the new debounced function.
- * @example
- *
- * // avoid costly calculations while the window size is in flux
- * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
- *
- * // invoke `sendMail` when the click event is fired, debouncing subsequent calls
- * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
- * 'leading': true,
- * 'trailing': false
- * }));
- *
- * // ensure `batchLog` is invoked once after 1 second of debounced calls
- * var source = new EventSource('/stream');
- * jQuery(source).on('message', _.debounce(batchLog, 250, {
- * 'maxWait': 1000
- * }));
- *
- * // cancel a debounced call
- * var todoChanges = _.debounce(batchLog, 1000);
- * Object.observe(models.todo, todoChanges);
- *
- * Object.observe(models, function(changes) {
- * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
- * todoChanges.cancel();
- * }
- * }, ['delete']);
- *
- * // ...at some point `models.todo` is changed
- * models.todo.completed = true;
- *
- * // ...before 1 second has passed `models.todo` is deleted
- * // which cancels the debounced `todoChanges` call
- * delete models.todo;
- */
- function debounce(func, wait, options) {
- var args,
- maxTimeoutId,
- result,
- stamp,
- thisArg,
- timeoutId,
- trailingCall,
- lastCalled = 0,
- maxWait = false,
- trailing = true;
-
- if (typeof func != 'function') {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- wait = wait < 0 ? 0 : (+wait || 0);
- if (options === true) {
- var leading = true;
- trailing = false;
- } else if (isObject(options)) {
- leading = options.leading;
- maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);
- trailing = 'trailing' in options ? options.trailing : trailing;
- }
-
- function cancel() {
- if (timeoutId) {
- clearTimeout(timeoutId);
- }
- if (maxTimeoutId) {
- clearTimeout(maxTimeoutId);
- }
- maxTimeoutId = timeoutId = trailingCall = undefined;
- }
-
- function delayed() {
- var remaining = wait - (now() - stamp);
- if (remaining <= 0 || remaining > wait) {
- if (maxTimeoutId) {
- clearTimeout(maxTimeoutId);
- }
- var isCalled = trailingCall;
- maxTimeoutId = timeoutId = trailingCall = undefined;
- if (isCalled) {
- lastCalled = now();
- result = func.apply(thisArg, args);
- if (!timeoutId && !maxTimeoutId) {
- args = thisArg = null;
- }
- }
- } else {
- timeoutId = setTimeout(delayed, remaining);
- }
- }
-
- function maxDelayed() {
- if (timeoutId) {
- clearTimeout(timeoutId);
- }
- maxTimeoutId = timeoutId = trailingCall = undefined;
- if (trailing || (maxWait !== wait)) {
- lastCalled = now();
- result = func.apply(thisArg, args);
- if (!timeoutId && !maxTimeoutId) {
- args = thisArg = null;
- }
- }
- }
-
- function debounced() {
- args = arguments;
- stamp = now();
- thisArg = this;
- trailingCall = trailing && (timeoutId || !leading);
-
- if (maxWait === false) {
- var leadingCall = leading && !timeoutId;
- } else {
- if (!maxTimeoutId && !leading) {
- lastCalled = stamp;
- }
- var remaining = maxWait - (stamp - lastCalled),
- isCalled = remaining <= 0 || remaining > maxWait;
-
- if (isCalled) {
- if (maxTimeoutId) {
- maxTimeoutId = clearTimeout(maxTimeoutId);
- }
- lastCalled = stamp;
- result = func.apply(thisArg, args);
- }
- else if (!maxTimeoutId) {
- maxTimeoutId = setTimeout(maxDelayed, remaining);
- }
- }
- if (isCalled && timeoutId) {
- timeoutId = clearTimeout(timeoutId);
- }
- else if (!timeoutId && wait !== maxWait) {
- timeoutId = setTimeout(delayed, wait);
- }
- if (leadingCall) {
- isCalled = true;
- result = func.apply(thisArg, args);
- }
- if (isCalled && !timeoutId && !maxTimeoutId) {
- args = thisArg = null;
- }
- return result;
- }
- debounced.cancel = cancel;
- return debounced;
- }
-
- /**
- * Defers invoking the `func` until the current call stack has cleared. Any
- * additional arguments are provided to `func` when it is invoked.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to defer.
- * @param {...*} [args] The arguments to invoke the function with.
- * @returns {number} Returns the timer id.
- * @example
- *
- * _.defer(function(text) {
- * console.log(text);
- * }, 'deferred');
- * // logs 'deferred' after one or more milliseconds
- */
- var defer = restParam(function(func, args) {
- return baseDelay(func, 1, args);
- });
-
- /**
- * Invokes `func` after `wait` milliseconds. Any additional arguments are
- * provided to `func` when it is invoked.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to delay.
- * @param {number} wait The number of milliseconds to delay invocation.
- * @param {...*} [args] The arguments to invoke the function with.
- * @returns {number} Returns the timer id.
- * @example
- *
- * _.delay(function(text) {
- * console.log(text);
- * }, 1000, 'later');
- * // => logs 'later' after one second
- */
- var delay = restParam(function(func, wait, args) {
- return baseDelay(func, wait, args);
- });
-
- /**
- * Creates a function that returns the result of invoking the provided
- * functions with the `this` binding of the created function, where each
- * successive invocation is supplied the return value of the previous.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {...Function} [funcs] Functions to invoke.
- * @returns {Function} Returns the new function.
- * @example
- *
- * function square(n) {
- * return n * n;
- * }
- *
- * var addSquare = _.flow(_.add, square);
- * addSquare(1, 2);
- * // => 9
- */
- var flow = createFlow();
-
- /**
- * This method is like `_.flow` except that it creates a function that
- * invokes the provided functions from right to left.
- *
- * @static
- * @memberOf _
- * @alias backflow, compose
- * @category Function
- * @param {...Function} [funcs] Functions to invoke.
- * @returns {Function} Returns the new function.
- * @example
- *
- * function square(n) {
- * return n * n;
- * }
- *
- * var addSquare = _.flowRight(square, _.add);
- * addSquare(1, 2);
- * // => 9
- */
- var flowRight = createFlow(true);
-
- /**
- * Creates a function that memoizes the result of `func`. If `resolver` is
- * provided it determines the cache key for storing the result based on the
- * arguments provided to the memoized function. By default, the first argument
- * provided to the memoized function is coerced to a string and used as the
- * cache key. The `func` is invoked with the `this` binding of the memoized
- * function.
- *
- * **Note:** The cache is exposed as the `cache` property on the memoized
- * function. Its creation may be customized by replacing the `_.memoize.Cache`
- * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object)
- * method interface of `get`, `has`, and `set`.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to have its output memoized.
- * @param {Function} [resolver] The function to resolve the cache key.
- * @returns {Function} Returns the new memoizing function.
- * @example
- *
- * var upperCase = _.memoize(function(string) {
- * return string.toUpperCase();
- * });
- *
- * upperCase('fred');
- * // => 'FRED'
- *
- * // modifying the result cache
- * upperCase.cache.set('fred', 'BARNEY');
- * upperCase('fred');
- * // => 'BARNEY'
- *
- * // replacing `_.memoize.Cache`
- * var object = { 'user': 'fred' };
- * var other = { 'user': 'barney' };
- * var identity = _.memoize(_.identity);
- *
- * identity(object);
- * // => { 'user': 'fred' }
- * identity(other);
- * // => { 'user': 'fred' }
- *
- * _.memoize.Cache = WeakMap;
- * var identity = _.memoize(_.identity);
- *
- * identity(object);
- * // => { 'user': 'fred' }
- * identity(other);
- * // => { 'user': 'barney' }
- */
- function memoize(func, resolver) {
- if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- var memoized = function() {
- var args = arguments,
- cache = memoized.cache,
- key = resolver ? resolver.apply(this, args) : args[0];
-
- if (cache.has(key)) {
- return cache.get(key);
- }
- var result = func.apply(this, args);
- cache.set(key, result);
- return result;
- };
- memoized.cache = new memoize.Cache;
- return memoized;
- }
-
- /**
- * Creates a function that negates the result of the predicate `func`. The
- * `func` predicate is invoked with the `this` binding and arguments of the
- * created function.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} predicate The predicate to negate.
- * @returns {Function} Returns the new function.
- * @example
- *
- * function isEven(n) {
- * return n % 2 == 0;
- * }
- *
- * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
- * // => [1, 3, 5]
- */
- function negate(predicate) {
- if (typeof predicate != 'function') {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- return function() {
- return !predicate.apply(this, arguments);
- };
- }
-
- /**
- * Creates a function that is restricted to invoking `func` once. Repeat calls
- * to the function return the value of the first call. The `func` is invoked
- * with the `this` binding and arguments of the created function.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to restrict.
- * @returns {Function} Returns the new restricted function.
- * @example
- *
- * var initialize = _.once(createApplication);
- * initialize();
- * initialize();
- * // `initialize` invokes `createApplication` once
- */
- function once(func) {
- return before(2, func);
- }
-
- /**
- * Creates a function that invokes `func` with `partial` arguments prepended
- * to those provided to the new function. This method is like `_.bind` except
- * it does **not** alter the `this` binding.
- *
- * The `_.partial.placeholder` value, which defaults to `_` in monolithic
- * builds, may be used as a placeholder for partially applied arguments.
- *
- * **Note:** This method does not set the "length" property of partially
- * applied functions.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to partially apply arguments to.
- * @param {...*} [partials] The arguments to be partially applied.
- * @returns {Function} Returns the new partially applied function.
- * @example
- *
- * var greet = function(greeting, name) {
- * return greeting + ' ' + name;
- * };
- *
- * var sayHelloTo = _.partial(greet, 'hello');
- * sayHelloTo('fred');
- * // => 'hello fred'
- *
- * // using placeholders
- * var greetFred = _.partial(greet, _, 'fred');
- * greetFred('hi');
- * // => 'hi fred'
- */
- var partial = createPartial(PARTIAL_FLAG);
-
- /**
- * This method is like `_.partial` except that partially applied arguments
- * are appended to those provided to the new function.
- *
- * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
- * builds, may be used as a placeholder for partially applied arguments.
- *
- * **Note:** This method does not set the "length" property of partially
- * applied functions.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to partially apply arguments to.
- * @param {...*} [partials] The arguments to be partially applied.
- * @returns {Function} Returns the new partially applied function.
- * @example
- *
- * var greet = function(greeting, name) {
- * return greeting + ' ' + name;
- * };
- *
- * var greetFred = _.partialRight(greet, 'fred');
- * greetFred('hi');
- * // => 'hi fred'
- *
- * // using placeholders
- * var sayHelloTo = _.partialRight(greet, 'hello', _);
- * sayHelloTo('fred');
- * // => 'hello fred'
- */
- var partialRight = createPartial(PARTIAL_RIGHT_FLAG);
-
- /**
- * Creates a function that invokes `func` with arguments arranged according
- * to the specified indexes where the argument value at the first index is
- * provided as the first argument, the argument value at the second index is
- * provided as the second argument, and so on.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to rearrange arguments for.
- * @param {...(number|number[])} indexes The arranged argument indexes,
- * specified as individual indexes or arrays of indexes.
- * @returns {Function} Returns the new function.
- * @example
- *
- * var rearged = _.rearg(function(a, b, c) {
- * return [a, b, c];
- * }, 2, 0, 1);
- *
- * rearged('b', 'c', 'a')
- * // => ['a', 'b', 'c']
- *
- * var map = _.rearg(_.map, [1, 0]);
- * map(function(n) {
- * return n * 3;
- * }, [1, 2, 3]);
- * // => [3, 6, 9]
- */
- var rearg = restParam(function(func, indexes) {
- return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes));
- });
-
- /**
- * Creates a function that invokes `func` with the `this` binding of the
- * created function and arguments from `start` and beyond provided as an array.
- *
- * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to apply a rest parameter to.
- * @param {number} [start=func.length-1] The start position of the rest parameter.
- * @returns {Function} Returns the new function.
- * @example
- *
- * var say = _.restParam(function(what, names) {
- * return what + ' ' + _.initial(names).join(', ') +
- * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
- * });
- *
- * say('hello', 'fred', 'barney', 'pebbles');
- * // => 'hello fred, barney, & pebbles'
- */
- function restParam(func, start) {
- if (typeof func != 'function') {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
- return function() {
- var args = arguments,
- index = -1,
- length = nativeMax(args.length - start, 0),
- rest = Array(length);
-
- while (++index < length) {
- rest[index] = args[start + index];
- }
- switch (start) {
- case 0: return func.call(this, rest);
- case 1: return func.call(this, args[0], rest);
- case 2: return func.call(this, args[0], args[1], rest);
- }
- var otherArgs = Array(start + 1);
- index = -1;
- while (++index < start) {
- otherArgs[index] = args[index];
- }
- otherArgs[start] = rest;
- return func.apply(this, otherArgs);
- };
- }
-
- /**
- * Creates a function that invokes `func` with the `this` binding of the created
- * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3).
- *
- * **Note:** This method is based on the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator).
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to spread arguments over.
- * @returns {Function} Returns the new function.
- * @example
- *
- * var say = _.spread(function(who, what) {
- * return who + ' says ' + what;
- * });
- *
- * say(['fred', 'hello']);
- * // => 'fred says hello'
- *
- * // with a Promise
- * var numbers = Promise.all([
- * Promise.resolve(40),
- * Promise.resolve(36)
- * ]);
- *
- * numbers.then(_.spread(function(x, y) {
- * return x + y;
- * }));
- * // => a Promise of 76
- */
- function spread(func) {
- if (typeof func != 'function') {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- return function(array) {
- return func.apply(this, array);
- };
- }
-
- /**
- * Creates a function that only invokes `func` at most once per every `wait`
- * milliseconds. The created function comes with a `cancel` method to cancel
- * delayed invocations. Provide an options object to indicate that `func`
- * should be invoked on the leading and/or trailing edge of the `wait` timeout.
- * Subsequent calls to the throttled function return the result of the last
- * `func` call.
- *
- * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
- * on the trailing edge of the timeout only if the the throttled function is
- * invoked more than once during the `wait` timeout.
- *
- * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
- * for details over the differences between `_.throttle` and `_.debounce`.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {Function} func The function to throttle.
- * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
- * @param {Object} [options] The options object.
- * @param {boolean} [options.leading=true] Specify invoking on the leading
- * edge of the timeout.
- * @param {boolean} [options.trailing=true] Specify invoking on the trailing
- * edge of the timeout.
- * @returns {Function} Returns the new throttled function.
- * @example
- *
- * // avoid excessively updating the position while scrolling
- * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
- *
- * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
- * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
- * 'trailing': false
- * }));
- *
- * // cancel a trailing throttled call
- * jQuery(window).on('popstate', throttled.cancel);
- */
- function throttle(func, wait, options) {
- var leading = true,
- trailing = true;
-
- if (typeof func != 'function') {
- throw new TypeError(FUNC_ERROR_TEXT);
- }
- if (options === false) {
- leading = false;
- } else if (isObject(options)) {
- leading = 'leading' in options ? !!options.leading : leading;
- trailing = 'trailing' in options ? !!options.trailing : trailing;
- }
- debounceOptions.leading = leading;
- debounceOptions.maxWait = +wait;
- debounceOptions.trailing = trailing;
- return debounce(func, wait, debounceOptions);
- }
-
- /**
- * Creates a function that provides `value` to the wrapper function as its
- * first argument. Any additional arguments provided to the function are
- * appended to those provided to the wrapper function. The wrapper is invoked
- * with the `this` binding of the created function.
- *
- * @static
- * @memberOf _
- * @category Function
- * @param {*} value The value to wrap.
- * @param {Function} wrapper The wrapper function.
- * @returns {Function} Returns the new function.
- * @example
- *
- * var p = _.wrap(_.escape, function(func, text) {
- * return '