Project

General

Profile

Download (330 KB) Statistics
| Branch: | Revision:
1
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.dagre=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
/*
3
Copyright (c) 2012-2014 Chris Pettitt
4

    
5
Permission is hereby granted, free of charge, to any person obtaining a copy
6
of this software and associated documentation files (the "Software"), to deal
7
in the Software without restriction, including without limitation the rights
8
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
copies of the Software, and to permit persons to whom the Software is
10
furnished to do so, subject to the following conditions:
11

    
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
14

    
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
THE SOFTWARE.
22
*/
23

    
24
module.exports = {
25
  graphlib: require("./lib/graphlib"),
26

    
27
  layout: require("./lib/layout"),
28
  debug: require("./lib/debug"),
29
  util: {
30
    time: require("./lib/util").time,
31
    notime: require("./lib/util").notime
32
  },
33
  version: require("./lib/version")
34
};
35

    
36
},{"./lib/debug":6,"./lib/graphlib":7,"./lib/layout":9,"./lib/util":29,"./lib/version":30}],2:[function(require,module,exports){
37
"use strict";
38

    
39
var _ = require("./lodash"),
40
    greedyFAS = require("./greedy-fas");
41

    
42
module.exports = {
43
  run: run,
44
  undo: undo
45
};
46

    
47
function run(g) {
48
  var fas = (g.graph().acyclicer === "greedy"
49
                ? greedyFAS(g, weightFn(g))
50
                : dfsFAS(g));
51
  _.each(fas, function(e) {
52
    var label = g.edge(e);
53
    g.removeEdge(e);
54
    label.forwardName = e.name;
55
    label.reversed = true;
56
    g.setEdge(e.w, e.v, label, _.uniqueId("rev"));
57
  });
58

    
59
  function weightFn(g) {
60
    return function(e) {
61
      return g.edge(e).weight;
62
    };
63
  }
64
}
65

    
66
function dfsFAS(g) {
67
  var fas = [],
68
      stack = {},
69
      visited = {};
70

    
71
  function dfs(v) {
72
    if (_.has(visited, v)) {
73
      return;
74
    }
75
    visited[v] = true;
76
    stack[v] = true;
77
    _.each(g.outEdges(v), function(e) {
78
      if (_.has(stack, e.w)) {
79
        fas.push(e);
80
      } else {
81
        dfs(e.w);
82
      }
83
    });
84
    delete stack[v];
85
  }
86

    
87
  _.each(g.nodes(), dfs);
88
  return fas;
89
}
90

    
91
function undo(g) {
92
  _.each(g.edges(), function(e) {
93
    var label = g.edge(e);
94
    if (label.reversed) {
95
      g.removeEdge(e);
96

    
97
      var forwardName = label.forwardName;
98
      delete label.reversed;
99
      delete label.forwardName;
100
      g.setEdge(e.w, e.v, label, forwardName);
101
    }
102
  });
103
}
104

    
105
},{"./greedy-fas":8,"./lodash":10}],3:[function(require,module,exports){
106
var _ = require("./lodash"),
107
    util = require("./util");
108

    
109
module.exports = addBorderSegments;
110

    
111
function addBorderSegments(g) {
112
  function dfs(v) {
113
    var children = g.children(v),
114
        node = g.node(v);
115
    if (children.length) {
116
      _.each(children, dfs);
117
    }
118

    
119
    if (_.has(node, "minRank")) {
120
      node.borderLeft = [];
121
      node.borderRight = [];
122
      for (var rank = node.minRank, maxRank = node.maxRank + 1;
123
           rank < maxRank;
124
           ++rank) {
125
        addBorderNode(g, "borderLeft", "_bl", v, node, rank);
126
        addBorderNode(g, "borderRight", "_br", v, node, rank);
127
      }
128
    }
129
  }
130

    
131
  _.each(g.children(), dfs);
132
}
133

    
134
function addBorderNode(g, prop, prefix, sg, sgNode, rank) {
135
  var label = { width: 0, height: 0, rank: rank },
136
      prev = sgNode[prop][rank - 1],
137
      curr = util.addDummyNode(g, "border", label, prefix);
138
  sgNode[prop][rank] = curr;
139
  g.setParent(curr, sg);
140
  if (prev) {
141
    g.setEdge(prev, curr, { weight: 1 });
142
  }
143
}
144

    
145
},{"./lodash":10,"./util":29}],4:[function(require,module,exports){
146
"use strict";
147

    
148
var _ = require("./lodash");
149

    
150
module.exports = {
151
  adjust: adjust,
152
  undo: undo
153
};
154

    
155
function adjust(g) {
156
  var rankDir = g.graph().rankdir.toLowerCase();
157
  if (rankDir === "lr" || rankDir === "rl") {
158
    swapWidthHeight(g);
159
  }
160
}
161

    
162
function undo(g) {
163
  var rankDir = g.graph().rankdir.toLowerCase();
164
  if (rankDir === "bt" || rankDir === "rl") {
165
    reverseY(g);
166
  }
167

    
168
  if (rankDir === "lr" || rankDir === "rl") {
169
    swapXY(g);
170
    swapWidthHeight(g);
171
  }
172
}
173

    
174
function swapWidthHeight(g) {
175
  _.each(g.nodes(), function(v) { swapWidthHeightOne(g.node(v)); });
176
  _.each(g.edges(), function(e) { swapWidthHeightOne(g.edge(e)); });
177
}
178

    
179
function swapWidthHeightOne(attrs) {
180
  var w = attrs.width;
181
  attrs.width = attrs.height;
182
  attrs.height = w;
183
}
184

    
185
function reverseY(g) {
186
  _.each(g.nodes(), function(v) { reverseYOne(g.node(v)); });
187

    
188
  _.each(g.edges(), function(e) {
189
    var edge = g.edge(e);
190
    _.each(edge.points, reverseYOne);
191
    if (_.has(edge, "y")) {
192
      reverseYOne(edge);
193
    }
194
  });
195
}
196

    
197
function reverseYOne(attrs) {
198
  attrs.y = -attrs.y;
199
}
200

    
201
function swapXY(g) {
202
  _.each(g.nodes(), function(v) { swapXYOne(g.node(v)); });
203

    
204
  _.each(g.edges(), function(e) {
205
    var edge = g.edge(e);
206
    _.each(edge.points, swapXYOne);
207
    if (_.has(edge, "x")) {
208
      swapXYOne(edge);
209
    }
210
  });
211
}
212

    
213
function swapXYOne(attrs) {
214
  var x = attrs.x;
215
  attrs.x = attrs.y;
216
  attrs.y = x;
217
}
218

    
219
},{"./lodash":10}],5:[function(require,module,exports){
220
/*
221
 * Simple doubly linked list implementation derived from Cormen, et al.,
222
 * "Introduction to Algorithms".
223
 */
224

    
225
module.exports = List;
226

    
227
function List() {
228
  var sentinel = {};
229
  sentinel._next = sentinel._prev = sentinel;
230
  this._sentinel = sentinel;
231
}
232

    
233
List.prototype.dequeue = function() {
234
  var sentinel = this._sentinel,
235
      entry = sentinel._prev;
236
  if (entry !== sentinel) {
237
    unlink(entry);
238
    return entry;
239
  }
240
};
241

    
242
List.prototype.enqueue = function(entry) {
243
  var sentinel = this._sentinel;
244
  if (entry._prev && entry._next) {
245
    unlink(entry);
246
  }
247
  entry._next = sentinel._next;
248
  sentinel._next._prev = entry;
249
  sentinel._next = entry;
250
  entry._prev = sentinel;
251
};
252

    
253
List.prototype.toString = function() {
254
  var strs = [],
255
      sentinel = this._sentinel,
256
      curr = sentinel._prev;
257
  while (curr !== sentinel) {
258
    strs.push(JSON.stringify(curr, filterOutLinks));
259
    curr = curr._prev;
260
  }
261
  return "[" + strs.join(", ") + "]";
262
};
263

    
264
function unlink(entry) {
265
  entry._prev._next = entry._next;
266
  entry._next._prev = entry._prev;
267
  delete entry._next;
268
  delete entry._prev;
269
}
270

    
271
function filterOutLinks(k, v) {
272
  if (k !== "_next" && k !== "_prev") {
273
    return v;
274
  }
275
}
276

    
277
},{}],6:[function(require,module,exports){
278
var _ = require("./lodash"),
279
    util = require("./util"),
280
    Graph = require("./graphlib").Graph;
281

    
282
module.exports = {
283
  debugOrdering: debugOrdering
284
};
285

    
286
/* istanbul ignore next */
287
function debugOrdering(g) {
288
  var layerMatrix = util.buildLayerMatrix(g);
289

    
290
  var h = new Graph({ compound: true, multigraph: true }).setGraph({});
291

    
292
  _.each(g.nodes(), function(v) {
293
    h.setNode(v, { label: v });
294
    h.setParent(v, "layer" + g.node(v).rank);
295
  });
296

    
297
  _.each(g.edges(), function(e) {
298
    h.setEdge(e.v, e.w, {}, e.name);
299
  });
300

    
301
  _.each(layerMatrix, function(layer, i) {
302
    var layerV = "layer" + i;
303
    h.setNode(layerV, { rank: "same" });
304
    _.reduce(layer, function(u, v) {
305
      h.setEdge(u, v, { style: "invis" });
306
      return v;
307
    });
308
  });
309

    
310
  return h;
311
}
312

    
313
},{"./graphlib":7,"./lodash":10,"./util":29}],7:[function(require,module,exports){
314
/* global window */
315

    
316
var graphlib;
317

    
318
if (require) {
319
  try {
320
    graphlib = require("graphlib");
321
  } catch (e) {}
322
}
323

    
324
if (!graphlib) {
325
  graphlib = window.graphlib;
326
}
327

    
328
module.exports = graphlib;
329

    
330
},{"graphlib":31}],8:[function(require,module,exports){
331
var _ = require("./lodash"),
332
    Graph = require("./graphlib").Graph,
333
    List = require("./data/list");
334

    
335
/*
336
 * A greedy heuristic for finding a feedback arc set for a graph. A feedback
337
 * arc set is a set of edges that can be removed to make a graph acyclic.
338
 * The algorithm comes from: P. Eades, X. Lin, and W. F. Smyth, "A fast and
339
 * effective heuristic for the feedback arc set problem." This implementation
340
 * adjusts that from the paper to allow for weighted edges.
341
 */
342
module.exports = greedyFAS;
343

    
344
var DEFAULT_WEIGHT_FN = _.constant(1);
345

    
346
function greedyFAS(g, weightFn) {
347
  if (g.nodeCount() <= 1) {
348
    return [];
349
  }
350
  var state = buildState(g, weightFn || DEFAULT_WEIGHT_FN);
351
  var results = doGreedyFAS(state.graph, state.buckets, state.zeroIdx);
352

    
353
  // Expand multi-edges
354
  return _.flatten(_.map(results, function(e) {
355
    return g.outEdges(e.v, e.w);
356
  }), true);
357
}
358

    
359
function doGreedyFAS(g, buckets, zeroIdx) {
360
  var results = [],
361
      sources = buckets[buckets.length - 1],
362
      sinks = buckets[0];
363

    
364
  var entry;
365
  while (g.nodeCount()) {
366
    while ((entry = sinks.dequeue()))   { removeNode(g, buckets, zeroIdx, entry); }
367
    while ((entry = sources.dequeue())) { removeNode(g, buckets, zeroIdx, entry); }
368
    if (g.nodeCount()) {
369
      for (var i = buckets.length - 2; i > 0; --i) {
370
        entry = buckets[i].dequeue();
371
        if (entry) {
372
          results = results.concat(removeNode(g, buckets, zeroIdx, entry, true));
373
          break;
374
        }
375
      }
376
    }
377
  }
378

    
379
  return results;
380
}
381

    
382
function removeNode(g, buckets, zeroIdx, entry, collectPredecessors) {
383
  var results = collectPredecessors ? [] : undefined;
384

    
385
  _.each(g.inEdges(entry.v), function(edge) {
386
    var weight = g.edge(edge),
387
        uEntry = g.node(edge.v);
388

    
389
    if (collectPredecessors) {
390
      results.push({ v: edge.v, w: edge.w });
391
    }
392

    
393
    uEntry.out -= weight;
394
    assignBucket(buckets, zeroIdx, uEntry);
395
  });
396

    
397
  _.each(g.outEdges(entry.v), function(edge) {
398
    var weight = g.edge(edge),
399
        w = edge.w,
400
        wEntry = g.node(w);
401
    wEntry.in -= weight;
402
    assignBucket(buckets, zeroIdx, wEntry);
403
  });
404

    
405
  g.removeNode(entry.v);
406

    
407
  return results;
408
}
409

    
410
function buildState(g, weightFn) {
411
  var fasGraph = new Graph(),
412
      maxIn = 0,
413
      maxOut = 0;
414

    
415
  _.each(g.nodes(), function(v) {
416
    fasGraph.setNode(v, { v: v, in: 0, out: 0 });
417
  });
418

    
419
  // Aggregate weights on nodes, but also sum the weights across multi-edges
420
  // into a single edge for the fasGraph.
421
  _.each(g.edges(), function(e) {
422
    var prevWeight = fasGraph.edge(e.v, e.w) || 0,
423
        weight = weightFn(e),
424
        edgeWeight = prevWeight + weight;
425
    fasGraph.setEdge(e.v, e.w, edgeWeight);
426
    maxOut = Math.max(maxOut, fasGraph.node(e.v).out += weight);
427
    maxIn  = Math.max(maxIn,  fasGraph.node(e.w).in  += weight);
428
  });
429

    
430
  var buckets = _.range(maxOut + maxIn + 3).map(function() { return new List(); });
431
  var zeroIdx = maxIn + 1;
432

    
433
  _.each(fasGraph.nodes(), function(v) {
434
    assignBucket(buckets, zeroIdx, fasGraph.node(v));
435
  });
436

    
437
  return { graph: fasGraph, buckets: buckets, zeroIdx: zeroIdx };
438
}
439

    
440
function assignBucket(buckets, zeroIdx, entry) {
441
  if (!entry.out) {
442
    buckets[0].enqueue(entry);
443
  } else if (!entry.in) {
444
    buckets[buckets.length - 1].enqueue(entry);
445
  } else {
446
    buckets[entry.out - entry.in + zeroIdx].enqueue(entry);
447
  }
448
}
449

    
450
},{"./data/list":5,"./graphlib":7,"./lodash":10}],9:[function(require,module,exports){
451
"use strict";
452

    
453
var _ = require("./lodash"),
454
    acyclic = require("./acyclic"),
455
    normalize = require("./normalize"),
456
    rank = require("./rank"),
457
    normalizeRanks = require("./util").normalizeRanks,
458
    parentDummyChains = require("./parent-dummy-chains"),
459
    removeEmptyRanks = require("./util").removeEmptyRanks,
460
    nestingGraph = require("./nesting-graph"),
461
    addBorderSegments = require("./add-border-segments"),
462
    coordinateSystem = require("./coordinate-system"),
463
    order = require("./order"),
464
    position = require("./position"),
465
    util = require("./util"),
466
    Graph = require("./graphlib").Graph;
467

    
468
module.exports = layout;
469

    
470
function layout(g, opts) {
471
  var time = opts && opts.debugTiming ? util.time : util.notime;
472
  time("layout", function() {
473
    var layoutGraph = time("  buildLayoutGraph",
474
                               function() { return buildLayoutGraph(g); });
475
    time("  runLayout",        function() { runLayout(layoutGraph, time); });
476
    time("  updateInputGraph", function() { updateInputGraph(g, layoutGraph); });
477
  });
478
}
479

    
480
function runLayout(g, time) {
481
  time("    makeSpaceForEdgeLabels", function() { makeSpaceForEdgeLabels(g); });
482
  time("    removeSelfEdges",        function() { removeSelfEdges(g); });
483
  time("    acyclic",                function() { acyclic.run(g); });
484
  time("    nestingGraph.run",       function() { nestingGraph.run(g); });
485
  time("    rank",                   function() { rank(util.asNonCompoundGraph(g)); });
486
  time("    injectEdgeLabelProxies", function() { injectEdgeLabelProxies(g); });
487
  time("    removeEmptyRanks",       function() { removeEmptyRanks(g); });
488
  time("    nestingGraph.cleanup",   function() { nestingGraph.cleanup(g); });
489
  time("    normalizeRanks",         function() { normalizeRanks(g); });
490
  time("    assignRankMinMax",       function() { assignRankMinMax(g); });
491
  time("    removeEdgeLabelProxies", function() { removeEdgeLabelProxies(g); });
492
  time("    normalize.run",          function() { normalize.run(g); });
493
  time("    parentDummyChains",      function() { parentDummyChains(g); });
494
  time("    addBorderSegments",      function() { addBorderSegments(g); });
495
  time("    order",                  function() { order(g); });
496
  time("    insertSelfEdges",        function() { insertSelfEdges(g); });
497
  time("    adjustCoordinateSystem", function() { coordinateSystem.adjust(g); });
498
  time("    position",               function() { position(g); });
499
  time("    positionSelfEdges",      function() { positionSelfEdges(g); });
500
  time("    removeBorderNodes",      function() { removeBorderNodes(g); });
501
  time("    normalize.undo",         function() { normalize.undo(g); });
502
  time("    fixupEdgeLabelCoords",   function() { fixupEdgeLabelCoords(g); });
503
  time("    undoCoordinateSystem",   function() { coordinateSystem.undo(g); });
504
  time("    translateGraph",         function() { translateGraph(g); });
505
  time("    assignNodeIntersects",   function() { assignNodeIntersects(g); });
506
  time("    reversePoints",          function() { reversePointsForReversedEdges(g); });
507
  time("    acyclic.undo",           function() { acyclic.undo(g); });
508
}
509

    
510
/*
511
 * Copies final layout information from the layout graph back to the input
512
 * graph. This process only copies whitelisted attributes from the layout graph
513
 * to the input graph, so it serves as a good place to determine what
514
 * attributes can influence layout.
515
 */
516
function updateInputGraph(inputGraph, layoutGraph) {
517
  _.each(inputGraph.nodes(), function(v) {
518
    var inputLabel = inputGraph.node(v),
519
        layoutLabel = layoutGraph.node(v);
520

    
521
    if (inputLabel) {
522
      inputLabel.x = layoutLabel.x;
523
      inputLabel.y = layoutLabel.y;
524

    
525
      if (layoutGraph.children(v).length) {
526
        inputLabel.width = layoutLabel.width;
527
        inputLabel.height = layoutLabel.height;
528
      }
529
    }
530
  });
531

    
532
  _.each(inputGraph.edges(), function(e) {
533
    var inputLabel = inputGraph.edge(e),
534
        layoutLabel = layoutGraph.edge(e);
535

    
536
    inputLabel.points = layoutLabel.points;
537
    if (_.has(layoutLabel, "x")) {
538
      inputLabel.x = layoutLabel.x;
539
      inputLabel.y = layoutLabel.y;
540
    }
541
  });
542

    
543
  inputGraph.graph().width = layoutGraph.graph().width;
544
  inputGraph.graph().height = layoutGraph.graph().height;
545
}
546

    
547
var graphNumAttrs = ["nodesep", "edgesep", "ranksep", "marginx", "marginy"],
548
    graphDefaults = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: "tb" },
549
    graphAttrs = ["acyclicer", "ranker", "rankdir", "align"],
550
    nodeNumAttrs = ["width", "height"],
551
    nodeDefaults = { width: 0, height: 0 },
552
    edgeNumAttrs = ["minlen", "weight", "width", "height", "labeloffset"],
553
    edgeDefaults = {
554
      minlen: 1, weight: 1, width: 0, height: 0,
555
      labeloffset: 10, labelpos: "r"
556
    },
557
    edgeAttrs = ["labelpos"];
558

    
559
/*
560
 * Constructs a new graph from the input graph, which can be used for layout.
561
 * This process copies only whitelisted attributes from the input graph to the
562
 * layout graph. Thus this function serves as a good place to determine what
563
 * attributes can influence layout.
564
 */
565
function buildLayoutGraph(inputGraph) {
566
  var g = new Graph({ multigraph: true, compound: true }),
567
      graph = canonicalize(inputGraph.graph());
568

    
569
  g.setGraph(_.merge({},
570
    graphDefaults,
571
    selectNumberAttrs(graph, graphNumAttrs),
572
    _.pick(graph, graphAttrs)));
573

    
574
  _.each(inputGraph.nodes(), function(v) {
575
    var node = canonicalize(inputGraph.node(v));
576
    g.setNode(v, _.defaults(selectNumberAttrs(node, nodeNumAttrs), nodeDefaults));
577
    g.setParent(v, inputGraph.parent(v));
578
  });
579

    
580
  _.each(inputGraph.edges(), function(e) {
581
    var edge = canonicalize(inputGraph.edge(e));
582
    g.setEdge(e, _.merge({},
583
      edgeDefaults,
584
      selectNumberAttrs(edge, edgeNumAttrs),
585
      _.pick(edge, edgeAttrs)));
586
  });
587

    
588
  return g;
589
}
590

    
591
/*
592
 * This idea comes from the Gansner paper: to account for edge labels in our
593
 * layout we split each rank in half by doubling minlen and halving ranksep.
594
 * Then we can place labels at these mid-points between nodes.
595
 *
596
 * We also add some minimal padding to the width to push the label for the edge
597
 * away from the edge itself a bit.
598
 */
599
function makeSpaceForEdgeLabels(g) {
600
  var graph = g.graph();
601
  graph.ranksep /= 2;
602
  _.each(g.edges(), function(e) {
603
    var edge = g.edge(e);
604
    edge.minlen *= 2;
605
    if (edge.labelpos.toLowerCase() !== "c") {
606
      if (graph.rankdir === "TB" || graph.rankdir === "BT") {
607
        edge.width += edge.labeloffset;
608
      } else {
609
        edge.height += edge.labeloffset;
610
      }
611
    }
612
  });
613
}
614

    
615
/*
616
 * Creates temporary dummy nodes that capture the rank in which each edge's
617
 * label is going to, if it has one of non-zero width and height. We do this
618
 * so that we can safely remove empty ranks while preserving balance for the
619
 * label's position.
620
 */
621
function injectEdgeLabelProxies(g) {
622
  _.each(g.edges(), function(e) {
623
    var edge = g.edge(e);
624
    if (edge.width && edge.height) {
625
      var v = g.node(e.v),
626
          w = g.node(e.w),
627
          label = { rank: (w.rank - v.rank) / 2 + v.rank, e: e };
628
      util.addDummyNode(g, "edge-proxy", label, "_ep");
629
    }
630
  });
631
}
632

    
633
function assignRankMinMax(g) {
634
  var maxRank = 0;
635
  _.each(g.nodes(), function(v) {
636
    var node = g.node(v);
637
    if (node.borderTop) {
638
      node.minRank = g.node(node.borderTop).rank;
639
      node.maxRank = g.node(node.borderBottom).rank;
640
      maxRank = _.max(maxRank, node.maxRank);
641
    }
642
  });
643
  g.graph().maxRank = maxRank;
644
}
645

    
646
function removeEdgeLabelProxies(g) {
647
  _.each(g.nodes(), function(v) {
648
    var node = g.node(v);
649
    if (node.dummy === "edge-proxy") {
650
      g.edge(node.e).labelRank = node.rank;
651
      g.removeNode(v);
652
    }
653
  });
654
}
655

    
656
function translateGraph(g) {
657
  var minX = Number.POSITIVE_INFINITY,
658
      maxX = 0,
659
      minY = Number.POSITIVE_INFINITY,
660
      maxY = 0,
661
      graphLabel = g.graph(),
662
      marginX = graphLabel.marginx || 0,
663
      marginY = graphLabel.marginy || 0;
664

    
665
  function getExtremes(attrs) {
666
    var x = attrs.x,
667
        y = attrs.y,
668
        w = attrs.width,
669
        h = attrs.height;
670
    minX = Math.min(minX, x - w / 2);
671
    maxX = Math.max(maxX, x + w / 2);
672
    minY = Math.min(minY, y - h / 2);
673
    maxY = Math.max(maxY, y + h / 2);
674
  }
675

    
676
  _.each(g.nodes(), function(v) { getExtremes(g.node(v)); });
677
  _.each(g.edges(), function(e) {
678
    var edge = g.edge(e);
679
    if (_.has(edge, "x")) {
680
      getExtremes(edge);
681
    }
682
  });
683

    
684
  minX -= marginX;
685
  minY -= marginY;
686

    
687
  _.each(g.nodes(), function(v) {
688
    var node = g.node(v);
689
    node.x -= minX;
690
    node.y -= minY;
691
  });
692

    
693
  _.each(g.edges(), function(e) {
694
    var edge = g.edge(e);
695
    _.each(edge.points, function(p) {
696
      p.x -= minX;
697
      p.y -= minY;
698
    });
699
    if (_.has(edge, "x")) { edge.x -= minX; }
700
    if (_.has(edge, "y")) { edge.y -= minY; }
701
  });
702

    
703
  graphLabel.width = maxX - minX + marginX;
704
  graphLabel.height = maxY - minY + marginY;
705
}
706

    
707
function assignNodeIntersects(g) {
708
  _.each(g.edges(), function(e) {
709
    var edge = g.edge(e),
710
        nodeV = g.node(e.v),
711
        nodeW = g.node(e.w),
712
        p1, p2;
713
    if (!edge.points) {
714
      edge.points = [];
715
      p1 = nodeW;
716
      p2 = nodeV;
717
    } else {
718
      p1 = edge.points[0];
719
      p2 = edge.points[edge.points.length - 1];
720
    }
721
    edge.points.unshift(util.intersectRect(nodeV, p1));
722
    edge.points.push(util.intersectRect(nodeW, p2));
723
  });
724
}
725

    
726
function fixupEdgeLabelCoords(g) {
727
  _.each(g.edges(), function(e) {
728
    var edge = g.edge(e);
729
    if (_.has(edge, "x")) {
730
      if (edge.labelpos === "l" || edge.labelpos === "r") {
731
        edge.width -= edge.labeloffset;
732
      }
733
      switch (edge.labelpos) {
734
        case "l": edge.x -= edge.width / 2 + edge.labeloffset; break;
735
        case "r": edge.x += edge.width / 2 + edge.labeloffset; break;
736
      }
737
    }
738
  });
739
}
740

    
741
function reversePointsForReversedEdges(g) {
742
  _.each(g.edges(), function(e) {
743
    var edge = g.edge(e);
744
    if (edge.reversed) {
745
      edge.points.reverse();
746
    }
747
  });
748
}
749

    
750
function removeBorderNodes(g) {
751
  _.each(g.nodes(), function(v) {
752
    if (g.children(v).length) {
753
      var node = g.node(v),
754
          t = g.node(node.borderTop),
755
          b = g.node(node.borderBottom),
756
          l = g.node(_.last(node.borderLeft)),
757
          r = g.node(_.last(node.borderRight));
758

    
759
      node.width = Math.abs(r.x - l.x);
760
      node.height = Math.abs(b.y - t.y);
761
      node.x = l.x + node.width / 2;
762
      node.y = t.y + node.height / 2;
763
    }
764
  });
765

    
766
  _.each(g.nodes(), function(v) {
767
    if (g.node(v).dummy === "border") {
768
      g.removeNode(v);
769
    }
770
  });
771
}
772

    
773
function removeSelfEdges(g) {
774
  _.each(g.edges(), function(e) {
775
    if (e.v === e.w) {
776
      var node = g.node(e.v);
777
      if (!node.selfEdges) {
778
        node.selfEdges = [];
779
      }
780
      node.selfEdges.push({ e: e, label: g.edge(e) });
781
      g.removeEdge(e);
782
    }
783
  });
784
}
785

    
786
function insertSelfEdges(g) {
787
  var layers = util.buildLayerMatrix(g);
788
  _.each(layers, function(layer) {
789
    var orderShift = 0;
790
    _.each(layer, function(v, i) {
791
      var node = g.node(v);
792
      node.order = i + orderShift;
793
      _.each(node.selfEdges, function(selfEdge) {
794
        util.addDummyNode(g, "selfedge", {
795
          width: selfEdge.label.width,
796
          height: selfEdge.label.height,
797
          rank: node.rank,
798
          order: i + (++orderShift),
799
          e: selfEdge.e,
800
          label: selfEdge.label
801
        }, "_se");
802
      });
803
      delete node.selfEdges;
804
    });
805
  });
806
}
807

    
808
function positionSelfEdges(g) {
809
  _.each(g.nodes(), function(v) {
810
    var node = g.node(v);
811
    if (node.dummy === "selfedge") {
812
      var selfNode = g.node(node.e.v),
813
          x = selfNode.x + selfNode.width / 2,
814
          y = selfNode.y,
815
          dx = node.x - x,
816
          dy = selfNode.height / 2;
817
      g.setEdge(node.e, node.label);
818
      g.removeNode(v);
819
      node.label.points = [
820
        { x: x + 2 * dx / 3, y: y - dy },
821
        { x: x + 5 * dx / 6, y: y - dy },
822
        { x: x +     dx    , y: y },
823
        { x: x + 5 * dx / 6, y: y + dy },
824
        { x: x + 2 * dx / 3, y: y + dy },
825
      ];
826
      node.label.x = node.x;
827
      node.label.y = node.y;
828
    }
829
  });
830
}
831

    
832
function selectNumberAttrs(obj, attrs) {
833
  return _.mapValues(_.pick(obj, attrs), Number);
834
}
835

    
836
function canonicalize(attrs) {
837
  var newAttrs = {};
838
  _.each(attrs, function(v, k) {
839
    newAttrs[k.toLowerCase()] = v;
840
  });
841
  return newAttrs;
842
}
843

    
844
},{"./acyclic":2,"./add-border-segments":3,"./coordinate-system":4,"./graphlib":7,"./lodash":10,"./nesting-graph":11,"./normalize":12,"./order":17,"./parent-dummy-chains":22,"./position":24,"./rank":26,"./util":29}],10:[function(require,module,exports){
845
/* global window */
846

    
847
var lodash;
848

    
849
if (require) {
850
  try {
851
    lodash = require("lodash");
852
  } catch (e) {}
853
}
854

    
855
if (!lodash) {
856
  lodash = window._;
857
}
858

    
859
module.exports = lodash;
860

    
861
},{"lodash":51}],11:[function(require,module,exports){
862
var _ = require("./lodash"),
863
    util = require("./util");
864

    
865
module.exports = {
866
  run: run,
867
  cleanup: cleanup
868
};
869

    
870
/*
871
 * A nesting graph creates dummy nodes for the tops and bottoms of subgraphs,
872
 * adds appropriate edges to ensure that all cluster nodes are placed between
873
 * these boundries, and ensures that the graph is connected.
874
 *
875
 * In addition we ensure, through the use of the minlen property, that nodes
876
 * and subgraph border nodes to not end up on the same rank.
877
 *
878
 * Preconditions:
879
 *
880
 *    1. Input graph is a DAG
881
 *    2. Nodes in the input graph has a minlen attribute
882
 *
883
 * Postconditions:
884
 *
885
 *    1. Input graph is connected.
886
 *    2. Dummy nodes are added for the tops and bottoms of subgraphs.
887
 *    3. The minlen attribute for nodes is adjusted to ensure nodes do not
888
 *       get placed on the same rank as subgraph border nodes.
889
 *
890
 * The nesting graph idea comes from Sander, "Layout of Compound Directed
891
 * Graphs."
892
 */
893
function run(g) {
894
  var root = util.addDummyNode(g, "root", {}, "_root"),
895
      depths = treeDepths(g),
896
      height = _.max(depths) - 1,
897
      nodeSep = 2 * height + 1;
898

    
899
  g.graph().nestingRoot = root;
900

    
901
  // Multiply minlen by nodeSep to align nodes on non-border ranks.
902
  _.each(g.edges(), function(e) { g.edge(e).minlen *= nodeSep; });
903

    
904
  // Calculate a weight that is sufficient to keep subgraphs vertically compact
905
  var weight = sumWeights(g) + 1;
906

    
907
  // Create border nodes and link them up
908
  _.each(g.children(), function(child) {
909
    dfs(g, root, nodeSep, weight, height, depths, child);
910
  });
911

    
912
  // Save the multiplier for node layers for later removal of empty border
913
  // layers.
914
  g.graph().nodeRankFactor = nodeSep;
915
}
916

    
917
function dfs(g, root, nodeSep, weight, height, depths, v) {
918
  var children = g.children(v);
919
  if (!children.length) {
920
    if (v !== root) {
921
      g.setEdge(root, v, { weight: 0, minlen: nodeSep });
922
    }
923
    return;
924
  }
925

    
926
  var top = util.addBorderNode(g, "_bt"),
927
      bottom = util.addBorderNode(g, "_bb"),
928
      label = g.node(v);
929

    
930
  g.setParent(top, v);
931
  label.borderTop = top;
932
  g.setParent(bottom, v);
933
  label.borderBottom = bottom;
934

    
935
  _.each(children, function(child) {
936
    dfs(g, root, nodeSep, weight, height, depths, child);
937

    
938
    var childNode = g.node(child),
939
        childTop = childNode.borderTop ? childNode.borderTop : child,
940
        childBottom = childNode.borderBottom ? childNode.borderBottom : child,
941
        thisWeight = childNode.borderTop ? weight : 2 * weight,
942
        minlen = childTop !== childBottom ? 1 : height - depths[v] + 1;
943

    
944
    g.setEdge(top, childTop, {
945
      weight: thisWeight,
946
      minlen: minlen,
947
      nestingEdge: true
948
    });
949

    
950
    g.setEdge(childBottom, bottom, {
951
      weight: thisWeight,
952
      minlen: minlen,
953
      nestingEdge: true
954
    });
955
  });
956

    
957
  if (!g.parent(v)) {
958
    g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });
959
  }
960
}
961

    
962
function treeDepths(g) {
963
  var depths = {};
964
  function dfs(v, depth) {
965
    var children = g.children(v);
966
    if (children && children.length) {
967
      _.each(children, function(child) {
968
        dfs(child, depth + 1);
969
      });
970
    }
971
    depths[v] = depth;
972
  }
973
  _.each(g.children(), function(v) { dfs(v, 1); });
974
  return depths;
975
}
976

    
977
function sumWeights(g) {
978
  return _.reduce(g.edges(), function(acc, e) {
979
    return acc + g.edge(e).weight;
980
  }, 0);
981
}
982

    
983
function cleanup(g) {
984
  var graphLabel = g.graph();
985
  g.removeNode(graphLabel.nestingRoot);
986
  delete graphLabel.nestingRoot;
987
  _.each(g.edges(), function(e) {
988
    var edge = g.edge(e);
989
    if (edge.nestingEdge) {
990
      g.removeEdge(e);
991
    }
992
  });
993
}
994

    
995
},{"./lodash":10,"./util":29}],12:[function(require,module,exports){
996
"use strict";
997

    
998
var _ = require("./lodash"),
999
    util = require("./util");
1000

    
1001
module.exports = {
1002
  run: run,
1003
  undo: undo
1004
};
1005

    
1006
/*
1007
 * Breaks any long edges in the graph into short segments that span 1 layer
1008
 * each. This operation is undoable with the denormalize function.
1009
 *
1010
 * Pre-conditions:
1011
 *
1012
 *    1. The input graph is a DAG.
1013
 *    2. Each node in the graph has a "rank" property.
1014
 *
1015
 * Post-condition:
1016
 *
1017
 *    1. All edges in the graph have a length of 1.
1018
 *    2. Dummy nodes are added where edges have been split into segments.
1019
 *    3. The graph is augmented with a "dummyChains" attribute which contains
1020
 *       the first dummy in each chain of dummy nodes produced.
1021
 */
1022
function run(g) {
1023
  g.graph().dummyChains = [];
1024
  _.each(g.edges(), function(edge) { normalizeEdge(g, edge); });
1025
}
1026

    
1027
function normalizeEdge(g, e) {
1028
  var v = e.v,
1029
      vRank = g.node(v).rank,
1030
      w = e.w,
1031
      wRank = g.node(w).rank,
1032
      name = e.name,
1033
      edgeLabel = g.edge(e),
1034
      labelRank = edgeLabel.labelRank;
1035

    
1036
  if (wRank === vRank + 1) return;
1037

    
1038
  g.removeEdge(e);
1039

    
1040
  var dummy, attrs, i;
1041
  for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
1042
    edgeLabel.points = [];
1043
    attrs = {
1044
      width: 0, height: 0,
1045
      edgeLabel: edgeLabel, edgeObj: e,
1046
      rank: vRank
1047
    };
1048
    dummy = util.addDummyNode(g, "edge", attrs, "_d");
1049
    if (vRank === labelRank) {
1050
      attrs.width = edgeLabel.width;
1051
      attrs.height = edgeLabel.height;
1052
      attrs.dummy = "edge-label";
1053
      attrs.labelpos = edgeLabel.labelpos;
1054
    }
1055
    g.setEdge(v, dummy, { weight: edgeLabel.weight }, name);
1056
    if (i === 0) {
1057
      g.graph().dummyChains.push(dummy);
1058
    }
1059
    v = dummy;
1060
  }
1061

    
1062
  g.setEdge(v, w, { weight: edgeLabel.weight }, name);
1063
}
1064

    
1065
function undo(g) {
1066
  _.each(g.graph().dummyChains, function(v) {
1067
    var node = g.node(v),
1068
        origLabel = node.edgeLabel,
1069
        w;
1070
    g.setEdge(node.edgeObj, origLabel);
1071
    while (node.dummy) {
1072
      w = g.successors(v)[0];
1073
      g.removeNode(v);
1074
      origLabel.points.push({ x: node.x, y: node.y });
1075
      if (node.dummy === "edge-label") {
1076
        origLabel.x = node.x;
1077
        origLabel.y = node.y;
1078
        origLabel.width = node.width;
1079
        origLabel.height = node.height;
1080
      }
1081
      v = w;
1082
      node = g.node(v);
1083
    }
1084
  });
1085
}
1086

    
1087
},{"./lodash":10,"./util":29}],13:[function(require,module,exports){
1088
var _ = require("../lodash");
1089

    
1090
module.exports = addSubgraphConstraints;
1091

    
1092
function addSubgraphConstraints(g, cg, vs) {
1093
  var prev = {},
1094
      rootPrev;
1095

    
1096
  _.each(vs, function(v) {
1097
    var child = g.parent(v),
1098
        parent,
1099
        prevChild;
1100
    while (child) {
1101
      parent = g.parent(child);
1102
      if (parent) {
1103
        prevChild = prev[parent];
1104
        prev[parent] = child;
1105
      } else {
1106
        prevChild = rootPrev;
1107
        rootPrev = child;
1108
      }
1109
      if (prevChild && prevChild !== child) {
1110
        cg.setEdge(prevChild, child);
1111
        return;
1112
      }
1113
      child = parent;
1114
    }
1115
  });
1116

    
1117
  /*
1118
  function dfs(v) {
1119
    var children = v ? g.children(v) : g.children();
1120
    if (children.length) {
1121
      var min = Number.POSITIVE_INFINITY,
1122
          subgraphs = [];
1123
      _.each(children, function(child) {
1124
        var childMin = dfs(child);
1125
        if (g.children(child).length) {
1126
          subgraphs.push({ v: child, order: childMin });
1127
        }
1128
        min = Math.min(min, childMin);
1129
      });
1130
      _.reduce(_.sortBy(subgraphs, "order"), function(prev, curr) {
1131
        cg.setEdge(prev.v, curr.v);
1132
        return curr;
1133
      });
1134
      return min;
1135
    }
1136
    return g.node(v).order;
1137
  }
1138
  dfs(undefined);
1139
  */
1140
}
1141

    
1142
},{"../lodash":10}],14:[function(require,module,exports){
1143
var _ = require("../lodash");
1144

    
1145
module.exports = barycenter;
1146

    
1147
function barycenter(g, movable) {
1148
  return _.map(movable, function(v) {
1149
    var inV = g.inEdges(v);
1150
    if (!inV.length) {
1151
      return { v: v };
1152
    } else {
1153
      var result = _.reduce(inV, function(acc, e) {
1154
        var edge = g.edge(e),
1155
            nodeU = g.node(e.v);
1156
        return {
1157
          sum: acc.sum + (edge.weight * nodeU.order),
1158
          weight: acc.weight + edge.weight
1159
        };
1160
      }, { sum: 0, weight: 0 });
1161

    
1162
      return {
1163
        v: v,
1164
        barycenter: result.sum / result.weight,
1165
        weight: result.weight
1166
      };
1167
    }
1168
  });
1169
}
1170

    
1171

    
1172
},{"../lodash":10}],15:[function(require,module,exports){
1173
var _ = require("../lodash"),
1174
    Graph = require("../graphlib").Graph;
1175

    
1176
module.exports = buildLayerGraph;
1177

    
1178
/*
1179
 * Constructs a graph that can be used to sort a layer of nodes. The graph will
1180
 * contain all base and subgraph nodes from the request layer in their original
1181
 * hierarchy and any edges that are incident on these nodes and are of the type
1182
 * requested by the "relationship" parameter.
1183
 *
1184
 * Nodes from the requested rank that do not have parents are assigned a root
1185
 * node in the output graph, which is set in the root graph attribute. This
1186
 * makes it easy to walk the hierarchy of movable nodes during ordering.
1187
 *
1188
 * Pre-conditions:
1189
 *
1190
 *    1. Input graph is a DAG
1191
 *    2. Base nodes in the input graph have a rank attribute
1192
 *    3. Subgraph nodes in the input graph has minRank and maxRank attributes
1193
 *    4. Edges have an assigned weight
1194
 *
1195
 * Post-conditions:
1196
 *
1197
 *    1. Output graph has all nodes in the movable rank with preserved
1198
 *       hierarchy.
1199
 *    2. Root nodes in the movable layer are made children of the node
1200
 *       indicated by the root attribute of the graph.
1201
 *    3. Non-movable nodes incident on movable nodes, selected by the
1202
 *       relationship parameter, are included in the graph (without hierarchy).
1203
 *    4. Edges incident on movable nodes, selected by the relationship
1204
 *       parameter, are added to the output graph.
1205
 *    5. The weights for copied edges are aggregated as need, since the output
1206
 *       graph is not a multi-graph.
1207
 */
1208
function buildLayerGraph(g, rank, relationship) {
1209
  var root = createRootNode(g),
1210
      result = new Graph({ compound: true }).setGraph({ root: root })
1211
                  .setDefaultNodeLabel(function(v) { return g.node(v); });
1212

    
1213
  _.each(g.nodes(), function(v) {
1214
    var node = g.node(v),
1215
        parent = g.parent(v);
1216

    
1217
    if (node.rank === rank || node.minRank <= rank && rank <= node.maxRank) {
1218
      result.setNode(v);
1219
      result.setParent(v, parent || root);
1220

    
1221
      // This assumes we have only short edges!
1222
      _.each(g[relationship](v), function(e) {
1223
        var u = e.v === v ? e.w : e.v,
1224
            edge = result.edge(u, v),
1225
            weight = !_.isUndefined(edge) ? edge.weight : 0;
1226
        result.setEdge(u, v, { weight: g.edge(e).weight + weight });
1227
      });
1228

    
1229
      if (_.has(node, "minRank")) {
1230
        result.setNode(v, {
1231
          borderLeft: node.borderLeft[rank],
1232
          borderRight: node.borderRight[rank]
1233
        });
1234
      }
1235
    }
1236
  });
1237

    
1238
  return result;
1239
}
1240

    
1241
function createRootNode(g) {
1242
  var v;
1243
  while (g.hasNode((v = _.uniqueId("_root"))));
1244
  return v;
1245
}
1246

    
1247
},{"../graphlib":7,"../lodash":10}],16:[function(require,module,exports){
1248
"use strict";
1249

    
1250
var _ = require("../lodash");
1251

    
1252
module.exports = crossCount;
1253

    
1254
/*
1255
 * A function that takes a layering (an array of layers, each with an array of
1256
 * ordererd nodes) and a graph and returns a weighted crossing count.
1257
 *
1258
 * Pre-conditions:
1259
 *
1260
 *    1. Input graph must be simple (not a multigraph), directed, and include
1261
 *       only simple edges.
1262
 *    2. Edges in the input graph must have assigned weights.
1263
 *
1264
 * Post-conditions:
1265
 *
1266
 *    1. The graph and layering matrix are left unchanged.
1267
 *
1268
 * This algorithm is derived from Barth, et al., "Bilayer Cross Counting."
1269
 */
1270
function crossCount(g, layering) {
1271
  var cc = 0;
1272
  for (var i = 1; i < layering.length; ++i) {
1273
    cc += twoLayerCrossCount(g, layering[i-1], layering[i]);
1274
  }
1275
  return cc;
1276
}
1277

    
1278
function twoLayerCrossCount(g, northLayer, southLayer) {
1279
  // Sort all of the edges between the north and south layers by their position
1280
  // in the north layer and then the south. Map these edges to the position of
1281
  // their head in the south layer.
1282
  var southPos = _.zipObject(southLayer,
1283
                             _.map(southLayer, function (v, i) { return i; }));
1284
  var southEntries = _.flatten(_.map(northLayer, function(v) {
1285
    return _.chain(g.outEdges(v))
1286
            .map(function(e) {
1287
              return { pos: southPos[e.w], weight: g.edge(e).weight };
1288
            })
1289
            .sortBy("pos")
1290
            .value();
1291
  }), true);
1292

    
1293
  // Build the accumulator tree
1294
  var firstIndex = 1;
1295
  while (firstIndex < southLayer.length) firstIndex <<= 1;
1296
  var treeSize = 2 * firstIndex - 1;
1297
  firstIndex -= 1;
1298
  var tree = _.map(new Array(treeSize), function() { return 0; });
1299

    
1300
  // Calculate the weighted crossings
1301
  var cc = 0;
1302
  _.each(southEntries.forEach(function(entry) {
1303
    var index = entry.pos + firstIndex;
1304
    tree[index] += entry.weight;
1305
    var weightSum = 0;
1306
    while (index > 0) {
1307
      if (index % 2) {
1308
        weightSum += tree[index + 1];
1309
      }
1310
      index = (index - 1) >> 1;
1311
      tree[index] += entry.weight;
1312
    }
1313
    cc += entry.weight * weightSum;
1314
  }));
1315

    
1316
  return cc;
1317
}
1318

    
1319
},{"../lodash":10}],17:[function(require,module,exports){
1320
"use strict";
1321

    
1322
var _ = require("../lodash"),
1323
    initOrder = require("./init-order"),
1324
    crossCount = require("./cross-count"),
1325
    sortSubgraph = require("./sort-subgraph"),
1326
    buildLayerGraph = require("./build-layer-graph"),
1327
    addSubgraphConstraints = require("./add-subgraph-constraints"),
1328
    Graph = require("../graphlib").Graph,
1329
    util = require("../util");
1330

    
1331
module.exports = order;
1332

    
1333
/*
1334
 * Applies heuristics to minimize edge crossings in the graph and sets the best
1335
 * order solution as an order attribute on each node.
1336
 *
1337
 * Pre-conditions:
1338
 *
1339
 *    1. Graph must be DAG
1340
 *    2. Graph nodes must be objects with a "rank" attribute
1341
 *    3. Graph edges must have the "weight" attribute
1342
 *
1343
 * Post-conditions:
1344
 *
1345
 *    1. Graph nodes will have an "order" attribute based on the results of the
1346
 *       algorithm.
1347
 */
1348
function order(g) {
1349
  var maxRank = util.maxRank(g),
1350
      downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), "inEdges"),
1351
      upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), "outEdges");
1352

    
1353
  var layering = initOrder(g);
1354
  assignOrder(g, layering);
1355

    
1356
  var bestCC = Number.POSITIVE_INFINITY,
1357
      best;
1358

    
1359
  for (var i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
1360
    sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);
1361

    
1362
    layering = util.buildLayerMatrix(g);
1363
    var cc = crossCount(g, layering);
1364
    if (cc < bestCC) {
1365
      lastBest = 0;
1366
      best = _.cloneDeep(layering);
1367
      bestCC = cc;
1368
    }
1369
  }
1370

    
1371
  assignOrder(g, best);
1372
}
1373

    
1374
function buildLayerGraphs(g, ranks, relationship) {
1375
  return _.map(ranks, function(rank) {
1376
    return buildLayerGraph(g, rank, relationship);
1377
  });
1378
}
1379

    
1380
function sweepLayerGraphs(layerGraphs, biasRight) {
1381
  var cg = new Graph();
1382
  _.each(layerGraphs, function(lg) {
1383
    var root = lg.graph().root;
1384
    var sorted = sortSubgraph(lg, root, cg, biasRight);
1385
    _.each(sorted.vs, function(v, i) {
1386
      lg.node(v).order = i;
1387
    });
1388
    addSubgraphConstraints(lg, cg, sorted.vs);
1389
  });
1390
}
1391

    
1392
function assignOrder(g, layering) {
1393
  _.each(layering, function(layer) {
1394
    _.each(layer, function(v, i) {
1395
      g.node(v).order = i;
1396
    });
1397
  });
1398
}
1399

    
1400
},{"../graphlib":7,"../lodash":10,"../util":29,"./add-subgraph-constraints":13,"./build-layer-graph":15,"./cross-count":16,"./init-order":18,"./sort-subgraph":20}],18:[function(require,module,exports){
1401
"use strict";
1402

    
1403
var _ = require("../lodash");
1404

    
1405
module.exports = initOrder;
1406

    
1407
/*
1408
 * Assigns an initial order value for each node by performing a DFS search
1409
 * starting from nodes in the first rank. Nodes are assigned an order in their
1410
 * rank as they are first visited.
1411
 *
1412
 * This approach comes from Gansner, et al., "A Technique for Drawing Directed
1413
 * Graphs."
1414
 *
1415
 * Returns a layering matrix with an array per layer and each layer sorted by
1416
 * the order of its nodes.
1417
 */
1418
function initOrder(g) {
1419
  var visited = {},
1420
      simpleNodes = _.filter(g.nodes(), function(v) {
1421
        return !g.children(v).length;
1422
      }),
1423
      maxRank = _.max(_.map(simpleNodes, function(v) { return g.node(v).rank; })),
1424
      layers = _.map(_.range(maxRank + 1), function() { return []; });
1425

    
1426
  function dfs(v) {
1427
    if (_.has(visited, v)) return;
1428
    visited[v] = true;
1429
    var node = g.node(v);
1430
    layers[node.rank].push(v);
1431
    _.each(g.successors(v), dfs);
1432
  }
1433

    
1434
  var orderedVs = _.sortBy(simpleNodes, function(v) { return g.node(v).rank; });
1435
  _.each(orderedVs, dfs);
1436

    
1437
  return layers;
1438
}
1439

    
1440
},{"../lodash":10}],19:[function(require,module,exports){
1441
"use strict";
1442

    
1443
var _ = require("../lodash");
1444

    
1445
module.exports = resolveConflicts;
1446

    
1447
/*
1448
 * Given a list of entries of the form {v, barycenter, weight} and a
1449
 * constraint graph this function will resolve any conflicts between the
1450
 * constraint graph and the barycenters for the entries. If the barycenters for
1451
 * an entry would violate a constraint in the constraint graph then we coalesce
1452
 * the nodes in the conflict into a new node that respects the contraint and
1453
 * aggregates barycenter and weight information.
1454
 *
1455
 * This implementation is based on the description in Forster, "A Fast and
1456
 * Simple Hueristic for Constrained Two-Level Crossing Reduction," thought it
1457
 * differs in some specific details.
1458
 *
1459
 * Pre-conditions:
1460
 *
1461
 *    1. Each entry has the form {v, barycenter, weight}, or if the node has
1462
 *       no barycenter, then {v}.
1463
 *
1464
 * Returns:
1465
 *
1466
 *    A new list of entries of the form {vs, i, barycenter, weight}. The list
1467
 *    `vs` may either be a singleton or it may be an aggregation of nodes
1468
 *    ordered such that they do not violate constraints from the constraint
1469
 *    graph. The property `i` is the lowest original index of any of the
1470
 *    elements in `vs`.
1471
 */
1472
function resolveConflicts(entries, cg) {
1473
  var mappedEntries = {};
1474
  _.each(entries, function(entry, i) {
1475
    var tmp = mappedEntries[entry.v] = {
1476
      indegree: 0,
1477
      in: [],
1478
      out: [],
1479
      vs: [entry.v],
1480
      i: i
1481
    };
1482
    if (!_.isUndefined(entry.barycenter)) {
1483
      tmp.barycenter = entry.barycenter;
1484
      tmp.weight = entry.weight;
1485
    }
1486
  });
1487

    
1488
  _.each(cg.edges(), function(e) {
1489
    var entryV = mappedEntries[e.v],
1490
        entryW = mappedEntries[e.w];
1491
    if (!_.isUndefined(entryV) && !_.isUndefined(entryW)) {
1492
      entryW.indegree++;
1493
      entryV.out.push(mappedEntries[e.w]);
1494
    }
1495
  });
1496

    
1497
  var sourceSet = _.filter(mappedEntries, function(entry) {
1498
    return !entry.indegree;
1499
  });
1500

    
1501
  return doResolveConflicts(sourceSet);
1502
}
1503

    
1504
function doResolveConflicts(sourceSet) {
1505
  var entries = [];
1506

    
1507
  function handleIn(vEntry) {
1508
    return function(uEntry) {
1509
      if (uEntry.merged) {
1510
        return;
1511
      }
1512
      if (_.isUndefined(uEntry.barycenter) ||
1513
          _.isUndefined(vEntry.barycenter) ||
1514
          uEntry.barycenter >= vEntry.barycenter) {
1515
        mergeEntries(vEntry, uEntry);
1516
      }
1517
    };
1518
  }
1519

    
1520
  function handleOut(vEntry) {
1521
    return function(wEntry) {
1522
      wEntry.in.push(vEntry);
1523
      if (--wEntry.indegree === 0) {
1524
        sourceSet.push(wEntry);
1525
      }
1526
    };
1527
  }
1528

    
1529
  while (sourceSet.length) {
1530
    var entry = sourceSet.pop();
1531
    entries.push(entry);
1532
    _.each(entry.in.reverse(), handleIn(entry));
1533
    _.each(entry.out, handleOut(entry));
1534
  }
1535

    
1536
  return _.chain(entries)
1537
          .filter(function(entry) { return !entry.merged; })
1538
          .map(function(entry) {
1539
            return _.pick(entry, ["vs", "i", "barycenter", "weight"]);
1540
          })
1541
          .value();
1542
}
1543

    
1544
function mergeEntries(target, source) {
1545
  var sum = 0,
1546
      weight = 0;
1547

    
1548
  if (target.weight) {
1549
    sum += target.barycenter * target.weight;
1550
    weight += target.weight;
1551
  }
1552

    
1553
  if (source.weight) {
1554
    sum += source.barycenter * source.weight;
1555
    weight += source.weight;
1556
  }
1557

    
1558
  target.vs = source.vs.concat(target.vs);
1559
  target.barycenter = sum / weight;
1560
  target.weight = weight;
1561
  target.i = Math.min(source.i, target.i);
1562
  source.merged = true;
1563
}
1564

    
1565
},{"../lodash":10}],20:[function(require,module,exports){
1566
var _ = require("../lodash"),
1567
    barycenter = require("./barycenter"),
1568
    resolveConflicts = require("./resolve-conflicts"),
1569
    sort = require("./sort");
1570

    
1571
module.exports = sortSubgraph;
1572

    
1573
function sortSubgraph(g, v, cg, biasRight) {
1574
  var movable = g.children(v),
1575
      node = g.node(v),
1576
      bl = node ? node.borderLeft : undefined,
1577
      br = node ? node.borderRight: undefined,
1578
      subgraphs = {};
1579

    
1580
  if (bl) {
1581
    movable = _.filter(movable, function(w) {
1582
      return w !== bl && w !== br;
1583
    });
1584
  }
1585

    
1586
  var barycenters = barycenter(g, movable);
1587
  _.each(barycenters, function(entry) {
1588
    if (g.children(entry.v).length) {
1589
      var subgraphResult = sortSubgraph(g, entry.v, cg, biasRight);
1590
      subgraphs[entry.v] = subgraphResult;
1591
      if (_.has(subgraphResult, "barycenter")) {
1592
        mergeBarycenters(entry, subgraphResult);
1593
      }
1594
    }
1595
  });
1596

    
1597
  var entries = resolveConflicts(barycenters, cg);
1598
  expandSubgraphs(entries, subgraphs);
1599

    
1600
  var result = sort(entries, biasRight);
1601

    
1602
  if (bl) {
1603
    result.vs = _.flatten([bl, result.vs, br], true);
1604
    if (g.predecessors(bl).length) {
1605
      var blPred = g.node(g.predecessors(bl)[0]),
1606
          brPred = g.node(g.predecessors(br)[0]);
1607
      if (!_.has(result, "barycenter")) {
1608
        result.barycenter = 0;
1609
        result.weight = 0;
1610
      }
1611
      result.barycenter = (result.barycenter * result.weight +
1612
                           blPred.order + brPred.order) / (result.weight + 2);
1613
      result.weight += 2;
1614
    }
1615
  }
1616

    
1617
  return result;
1618
}
1619

    
1620
function expandSubgraphs(entries, subgraphs) {
1621
  _.each(entries, function(entry) {
1622
    entry.vs = _.flatten(entry.vs.map(function(v) {
1623
      if (subgraphs[v]) {
1624
        return subgraphs[v].vs;
1625
      }
1626
      return v;
1627
    }), true);
1628
  });
1629
}
1630

    
1631
function mergeBarycenters(target, other) {
1632
  if (!_.isUndefined(target.barycenter)) {
1633
    target.barycenter = (target.barycenter * target.weight +
1634
                         other.barycenter * other.weight) /
1635
                        (target.weight + other.weight);
1636
    target.weight += other.weight;
1637
  } else {
1638
    target.barycenter = other.barycenter;
1639
    target.weight = other.weight;
1640
  }
1641
}
1642

    
1643
},{"../lodash":10,"./barycenter":14,"./resolve-conflicts":19,"./sort":21}],21:[function(require,module,exports){
1644
var _ = require("../lodash"),
1645
    util = require("../util");
1646

    
1647
module.exports = sort;
1648

    
1649
function sort(entries, biasRight) {
1650
  var parts = util.partition(entries, function(entry) {
1651
    return _.has(entry, "barycenter");
1652
  });
1653
  var sortable = parts.lhs,
1654
      unsortable = _.sortBy(parts.rhs, function(entry) { return -entry.i; }),
1655
      vs = [],
1656
      sum = 0,
1657
      weight = 0,
1658
      vsIndex = 0;
1659

    
1660
  sortable.sort(compareWithBias(!!biasRight));
1661

    
1662
  vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
1663

    
1664
  _.each(sortable, function (entry) {
1665
    vsIndex += entry.vs.length;
1666
    vs.push(entry.vs);
1667
    sum += entry.barycenter * entry.weight;
1668
    weight += entry.weight;
1669
    vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
1670
  });
1671

    
1672
  var result = { vs: _.flatten(vs, true) };
1673
  if (weight) {
1674
    result.barycenter = sum / weight;
1675
    result.weight = weight;
1676
  }
1677
  return result;
1678
}
1679

    
1680
function consumeUnsortable(vs, unsortable, index) {
1681
  var last;
1682
  while (unsortable.length && (last = _.last(unsortable)).i <= index) {
1683
    unsortable.pop();
1684
    vs.push(last.vs);
1685
    index++;
1686
  }
1687
  return index;
1688
}
1689

    
1690
function compareWithBias(bias) {
1691
  return function(entryV, entryW) {
1692
    if (entryV.barycenter < entryW.barycenter) {
1693
      return -1;
1694
    } else if (entryV.barycenter > entryW.barycenter) {
1695
      return 1;
1696
    }
1697

    
1698
    return !bias ? entryV.i - entryW.i : entryW.i - entryV.i;
1699
  };
1700
}
1701

    
1702
},{"../lodash":10,"../util":29}],22:[function(require,module,exports){
1703
var _ = require("./lodash");
1704

    
1705
module.exports = parentDummyChains;
1706

    
1707
function parentDummyChains(g) {
1708
  var postorderNums = postorder(g);
1709

    
1710
  _.each(g.graph().dummyChains, function(v) {
1711
    var node = g.node(v),
1712
        edgeObj = node.edgeObj,
1713
        pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w),
1714
        path = pathData.path,
1715
        lca = pathData.lca,
1716
        pathIdx = 0,
1717
        pathV = path[pathIdx],
1718
        ascending = true;
1719

    
1720
    while (v !== edgeObj.w) {
1721
      node = g.node(v);
1722

    
1723
      if (ascending) {
1724
        while ((pathV = path[pathIdx]) !== lca &&
1725
               g.node(pathV).maxRank < node.rank) {
1726
          pathIdx++;
1727
        }
1728

    
1729
        if (pathV === lca) {
1730
          ascending = false;
1731
        }
1732
      }
1733

    
1734
      if (!ascending) {
1735
        while (pathIdx < path.length - 1 &&
1736
               g.node(pathV = path[pathIdx + 1]).minRank <= node.rank) {
1737
          pathIdx++;
1738
        }
1739
        pathV = path[pathIdx];
1740
      }
1741

    
1742
      g.setParent(v, pathV);
1743
      v = g.successors(v)[0];
1744
    }
1745
  });
1746
}
1747

    
1748
// Find a path from v to w through the lowest common ancestor (LCA). Return the
1749
// full path and the LCA.
1750
function findPath(g, postorderNums, v, w) {
1751
  var vPath = [],
1752
      wPath = [],
1753
      low = Math.min(postorderNums[v].low, postorderNums[w].low),
1754
      lim = Math.max(postorderNums[v].lim, postorderNums[w].lim),
1755
      parent,
1756
      lca;
1757

    
1758
  // Traverse up from v to find the LCA
1759
  parent = v;
1760
  do {
1761
    parent = g.parent(parent);
1762
    vPath.push(parent);
1763
  } while (parent &&
1764
           (postorderNums[parent].low > low || lim > postorderNums[parent].lim));
1765
  lca = parent;
1766

    
1767
  // Traverse from w to LCA
1768
  parent = w;
1769
  while ((parent = g.parent(parent)) !== lca) {
1770
    wPath.push(parent);
1771
  }
1772

    
1773
  return { path: vPath.concat(wPath.reverse()), lca: lca };
1774
}
1775

    
1776
function postorder(g) {
1777
  var result = {},
1778
      lim = 0;
1779

    
1780
  function dfs(v) {
1781
    var low = lim;
1782
    _.each(g.children(v), dfs);
1783
    result[v] = { low: low, lim: lim++ };
1784
  }
1785
  _.each(g.children(), dfs);
1786

    
1787
  return result;
1788
}
1789

    
1790
},{"./lodash":10}],23:[function(require,module,exports){
1791
"use strict";
1792

    
1793
var _ = require("../lodash"),
1794
    util = require("../util");
1795

    
1796
/*
1797
 * This module provides coordinate assignment based on Brandes and Köpf, "Fast
1798
 * and Simple Horizontal Coordinate Assignment."
1799
 */
1800

    
1801
module.exports = {
1802
  positionX: positionX,
1803
  findType1Conflicts: findType1Conflicts,
1804
  findType2Conflicts: findType2Conflicts,
1805
  addConflict: addConflict,
1806
  hasConflict: hasConflict,
1807
  verticalAlignment: verticalAlignment,
1808
  horizontalCompaction: horizontalCompaction,
1809
  alignCoordinates: alignCoordinates,
1810
  findSmallestWidthAlignment: findSmallestWidthAlignment,
1811
  balance: balance
1812
};
1813

    
1814
/*
1815
 * Marks all edges in the graph with a type-1 conflict with the "type1Conflict"
1816
 * property. A type-1 conflict is one where a non-inner segment crosses an
1817
 * inner segment. An inner segment is an edge with both incident nodes marked
1818
 * with the "dummy" property.
1819
 *
1820
 * This algorithm scans layer by layer, starting with the second, for type-1
1821
 * conflicts between the current layer and the previous layer. For each layer
1822
 * it scans the nodes from left to right until it reaches one that is incident
1823
 * on an inner segment. It then scans predecessors to determine if they have
1824
 * edges that cross that inner segment. At the end a final scan is done for all
1825
 * nodes on the current rank to see if they cross the last visited inner
1826
 * segment.
1827
 *
1828
 * This algorithm (safely) assumes that a dummy node will only be incident on a
1829
 * single node in the layers being scanned.
1830
 */
1831
function findType1Conflicts(g, layering) {
1832
  var conflicts = {};
1833

    
1834
  function visitLayer(prevLayer, layer) {
1835
    var
1836
      // last visited node in the previous layer that is incident on an inner
1837
      // segment.
1838
      k0 = 0,
1839
      // Tracks the last node in this layer scanned for crossings with a type-1
1840
      // segment.
1841
      scanPos = 0,
1842
      prevLayerLength = prevLayer.length,
1843
      lastNode = _.last(layer);
1844

    
1845
    _.each(layer, function(v, i) {
1846
      var w = findOtherInnerSegmentNode(g, v),
1847
          k1 = w ? g.node(w).order : prevLayerLength;
1848

    
1849
      if (w || v === lastNode) {
1850
        _.each(layer.slice(scanPos, i +1), function(scanNode) {
1851
          _.each(g.predecessors(scanNode), function(u) {
1852
            var uLabel = g.node(u),
1853
                uPos = uLabel.order;
1854
            if ((uPos < k0 || k1 < uPos) &&
1855
                !(uLabel.dummy && g.node(scanNode).dummy)) {
1856
              addConflict(conflicts, u, scanNode);
1857
            }
1858
          });
1859
        });
1860
        scanPos = i + 1;
1861
        k0 = k1;
1862
      }
1863
    });
1864

    
1865
    return layer;
1866
  }
1867

    
1868
  _.reduce(layering, visitLayer);
1869
  return conflicts;
1870
}
1871

    
1872
function findType2Conflicts(g, layering) {
1873
  var conflicts = {};
1874

    
1875
  function scan(south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
1876
    var v;
1877
    _.each(_.range(southPos, southEnd), function(i) {
1878
      v = south[i];
1879
      if (g.node(v).dummy) {
1880
        _.each(g.predecessors(v), function(u) {
1881
          var uNode = g.node(u);
1882
          if (uNode.dummy &&
1883
              (uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
1884
            addConflict(conflicts, u, v);
1885
          }
1886
        });
1887
      }
1888
    });
1889
  }
1890

    
1891

    
1892
  function visitLayer(north, south) {
1893
    var prevNorthPos = -1,
1894
        nextNorthPos,
1895
        southPos = 0;
1896

    
1897
    _.each(south, function(v, southLookahead) {
1898
      if (g.node(v).dummy === "border") {
1899
        var predecessors = g.predecessors(v);
1900
        if (predecessors.length) {
1901
          nextNorthPos = g.node(predecessors[0]).order;
1902
          scan(south, southPos, southLookahead, prevNorthPos, nextNorthPos);
1903
          southPos = southLookahead;
1904
          prevNorthPos = nextNorthPos;
1905
        }
1906
      }
1907
      scan(south, southPos, south.length, nextNorthPos, north.length);
1908
    });
1909

    
1910
    return south;
1911
  }
1912

    
1913
  _.reduce(layering, visitLayer);
1914
  return conflicts;
1915
}
1916

    
1917
function findOtherInnerSegmentNode(g, v) {
1918
  if (g.node(v).dummy) {
1919
    return _.find(g.predecessors(v), function(u) {
1920
      return g.node(u).dummy;
1921
    });
1922
  }
1923
}
1924

    
1925
function addConflict(conflicts, v, w) {
1926
  if (v > w) {
1927
    var tmp = v;
1928
    v = w;
1929
    w = tmp;
1930
  }
1931

    
1932
  var conflictsV = conflicts[v];
1933
  if (!conflictsV) {
1934
    conflicts[v] = conflictsV = {};
1935
  }
1936
  conflictsV[w] = true;
1937
}
1938

    
1939
function hasConflict(conflicts, v, w) {
1940
  if (v > w) {
1941
    var tmp = v;
1942
    v = w;
1943
    w = tmp;
1944
  }
1945
  return _.has(conflicts[v], w);
1946
}
1947

    
1948
/*
1949
 * Try to align nodes into vertical "blocks" where possible. This algorithm
1950
 * attempts to align a node with one of its median neighbors. If the edge
1951
 * connecting a neighbor is a type-1 conflict then we ignore that possibility.
1952
 * If a previous node has already formed a block with a node after the node
1953
 * we're trying to form a block with, we also ignore that possibility - our
1954
 * blocks would be split in that scenario.
1955
 */
1956
function verticalAlignment(g, layering, conflicts, neighborFn) {
1957
  var root = {},
1958
      align = {},
1959
      pos = {};
1960

    
1961
  // We cache the position here based on the layering because the graph and
1962
  // layering may be out of sync. The layering matrix is manipulated to
1963
  // generate different extreme alignments.
1964
  _.each(layering, function(layer) {
1965
    _.each(layer, function(v, order) {
1966
      root[v] = v;
1967
      align[v] = v;
1968
      pos[v] = order;
1969
    });
1970
  });
1971

    
1972
  _.each(layering, function(layer) {
1973
    var prevIdx = -1;
1974
    _.each(layer, function(v) {
1975
      var ws = neighborFn(v);
1976
      if (ws.length) {
1977
        ws = _.sortBy(ws, function(w) { return pos[w]; });
1978
        var mp = (ws.length - 1) / 2;
1979
        for (var i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
1980
          var w = ws[i];
1981
          if (align[v] === v &&
1982
              prevIdx < pos[w] &&
1983
              !hasConflict(conflicts, v, w)) {
1984
            align[w] = v;
1985
            align[v] = root[v] = root[w];
1986
            prevIdx = pos[w];
1987
          }
1988
        }
1989
      }
1990
    });
1991
  });
1992

    
1993
  return { root: root, align: align };
1994
}
1995

    
1996
function horizontalCompaction(g, layering, root, align, reverseSep) {
1997
  // We use local variables for these parameters instead of manipulating the
1998
  // graph because it becomes more verbose to access them in a chained manner.
1999
  var shift = {},
2000
      shiftNeighbor = {},
2001
      sink = {},
2002
      xs = {},
2003
      pred = {},
2004
      graphLabel = g.graph(),
2005
      sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep);
2006

    
2007
  _.each(layering, function(layer) {
2008
    _.each(layer, function(v, order) {
2009
      sink[v] = v;
2010
      shift[v] = Number.POSITIVE_INFINITY;
2011
      pred[v] = layer[order - 1];
2012
    });
2013
  });
2014

    
2015
  _.each(g.nodes(), function(v) {
2016
    if (root[v] === v) {
2017
      placeBlock(g, layering, sepFn, root, align, shift, shiftNeighbor, sink, pred, xs, v);
2018
    }
2019
  });
2020

    
2021
  _.each(layering, function(layer) {
2022
    _.each(layer, function(v) {
2023
      xs[v] = xs[root[v]];
2024
      // This line differs from the source paper. See
2025
      // http://www.inf.uni-konstanz.de/~brandes/publications/ for details.
2026
      if (v === root[v] && shift[sink[root[v]]] < Number.POSITIVE_INFINITY) {
2027
        xs[v] += shift[sink[root[v]]];
2028

    
2029
        // Cascade shifts as necessary
2030
        var w = shiftNeighbor[sink[root[v]]];
2031
        if (w && shift[w] !== Number.POSITIVE_INFINITY) {
2032
          xs[v] += shift[w];
2033
        }
2034
      }
2035
    });
2036
  });
2037

    
2038
  return xs;
2039
}
2040

    
2041
function placeBlock(g, layering, sepFn, root, align, shift, shiftNeighbor, sink, pred, xs, v) {
2042
  if (_.has(xs, v)) return;
2043
  xs[v] = 0;
2044

    
2045
  var w = v,
2046
      u;
2047
  do {
2048
    if (pred[w]) {
2049
      u = root[pred[w]];
2050
      placeBlock(g, layering, sepFn, root, align, shift, shiftNeighbor, sink, pred, xs, u);
2051
      if (sink[v] === v) {
2052
        sink[v] = sink[u];
2053
      }
2054

    
2055
      var delta = sepFn(g, w, pred[w]);
2056
      if (sink[v] !== sink[u]) {
2057
        shift[sink[u]] = Math.min(shift[sink[u]], xs[v] - xs[u] - delta);
2058
        shiftNeighbor[sink[u]] = sink[v];
2059
      } else {
2060
        xs[v] = Math.max(xs[v], xs[u] + delta);
2061
      }
2062
    }
2063
    w = align[w];
2064
  } while (w !== v);
2065
}
2066

    
2067
/*
2068
 * Returns the alignment that has the smallest width of the given alignments.
2069
 */
2070
function findSmallestWidthAlignment(g, xss) {
2071
  return _.min(xss, function(xs) {
2072
    var min = _.min(xs, function(x, v) { return x - width(g, v) / 2; }),
2073
        max = _.max(xs, function(x, v) { return x + width(g, v) / 2; });
2074
    return max - min;
2075
  });
2076
}
2077

    
2078
/*
2079
 * Align the coordinates of each of the layout alignments such that
2080
 * left-biased alignments have their minimum coordinate at the same point as
2081
 * the minimum coordinate of the smallest width alignment and right-biased
2082
 * alignments have their maximum coordinate at the same point as the maximum
2083
 * coordinate of the smallest width alignment.
2084
 */
2085
function alignCoordinates(xss, alignTo) {
2086
  var alignToMin = _.min(alignTo),
2087
      alignToMax = _.max(alignTo);
2088

    
2089
  _.each(["u", "d"], function(vert) {
2090
    _.each(["l", "r"], function(horiz) {
2091
      var alignment = vert + horiz,
2092
          xs = xss[alignment],
2093
          delta;
2094
      if (xs === alignTo) return;
2095

    
2096
      delta = horiz === "l" ? alignToMin - _.min(xs) : alignToMax - _.max(xs);
2097

    
2098
      if (delta) {
2099
        xss[alignment] = _.mapValues(xs, function(x) { return x + delta; });
2100
      }
2101
    });
2102
  });
2103
}
2104

    
2105
function balance(xss, align) {
2106
  return _.mapValues(xss.ul, function(ignore, v) {
2107
    if (align) {
2108
      return xss[align.toLowerCase()][v];
2109
    } else {
2110
      var xs = _.sortBy(_.pluck(xss, v));
2111
      return (xs[1] + xs[2]) / 2;
2112
    }
2113
  });
2114
}
2115

    
2116
function positionX(g) {
2117
  var layering = util.buildLayerMatrix(g),
2118
      conflicts = _.merge(findType1Conflicts(g, layering),
2119
                          findType2Conflicts(g, layering));
2120

    
2121
  var xss = {},
2122
      adjustedLayering;
2123
  _.each(["u", "d"], function(vert) {
2124
    adjustedLayering = vert === "u" ? layering : _.values(layering).reverse();
2125
    _.each(["l", "r"], function(horiz) {
2126
      if (horiz === "r") {
2127
        adjustedLayering = _.map(adjustedLayering, function(inner) {
2128
          return _.values(inner).reverse();
2129
        });
2130
      }
2131

    
2132
      var neighborFn = _.bind(vert === "u" ? g.predecessors : g.successors, g);
2133
      var align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn);
2134
      var xs = horizontalCompaction(g, adjustedLayering,
2135
                                    align.root, align.align,
2136
                                    horiz === "r");
2137
      if (horiz === "r") {
2138
        xs = _.mapValues(xs, function(x) { return -x; });
2139
      }
2140
      xss[vert + horiz] = xs;
2141
    });
2142
  });
2143

    
2144
  var smallestWidth = findSmallestWidthAlignment(g, xss);
2145
  alignCoordinates(xss, smallestWidth);
2146
  return balance(xss, g.graph().align);
2147
}
2148

    
2149
function sep(nodeSep, edgeSep, reverseSep) {
2150
  return function(g, v, w) {
2151
    var vLabel = g.node(v),
2152
        wLabel = g.node(w),
2153
        sum = 0,
2154
        delta;
2155

    
2156
    sum += vLabel.width / 2;
2157
    if (_.has(vLabel, "labelpos")) {
2158
      switch (vLabel.labelpos.toLowerCase()) {
2159
        case "l": delta = -vLabel.width / 2; break;
2160
        case "r": delta = vLabel.width / 2; break;
2161
      }
2162
    }
2163
    if (delta) {
2164
      sum += reverseSep ? delta : -delta;
2165
    }
2166
    delta = 0;
2167

    
2168
    sum += (vLabel.dummy ? edgeSep : nodeSep) / 2;
2169
    sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;
2170

    
2171
    sum += wLabel.width / 2;
2172
    if (_.has(wLabel, "labelpos")) {
2173
      switch (wLabel.labelpos.toLowerCase()) {
2174
        case "l": delta = wLabel.width / 2; break;
2175
        case "r": delta = -wLabel.width / 2; break;
2176
      }
2177
    }
2178
    if (delta) {
2179
      sum += reverseSep ? delta : -delta;
2180
    }
2181
    delta = 0;
2182

    
2183
    return sum;
2184
  };
2185
}
2186

    
2187
function width(g, v) {
2188
  return g.node(v).width;
2189
}
2190

    
2191
},{"../lodash":10,"../util":29}],24:[function(require,module,exports){
2192
"use strict";
2193

    
2194
var _ = require("../lodash"),
2195
    util = require("../util"),
2196
    positionX = require("./bk").positionX;
2197

    
2198
module.exports = position;
2199

    
2200
function position(g) {
2201
  g = util.asNonCompoundGraph(g);
2202

    
2203
  positionY(g);
2204
  _.each(positionX(g), function(x, v) {
2205
    g.node(v).x = x;
2206
  });
2207
}
2208

    
2209
function positionY(g) {
2210
  var layering = util.buildLayerMatrix(g),
2211
      rankSep = g.graph().ranksep,
2212
      prevY = 0;
2213
  _.each(layering, function(layer) {
2214
    var maxHeight = _.max(_.map(layer, function(v) { return g.node(v).height; }));
2215
    _.each(layer, function(v) {
2216
      g.node(v).y = prevY + maxHeight / 2;
2217
    });
2218
    prevY += maxHeight + rankSep;
2219
  });
2220
}
2221

    
2222

    
2223
},{"../lodash":10,"../util":29,"./bk":23}],25:[function(require,module,exports){
2224
"use strict";
2225

    
2226
var _ = require("../lodash"),
2227
    Graph = require("../graphlib").Graph,
2228
    slack = require("./util").slack;
2229

    
2230
module.exports = feasibleTree;
2231

    
2232
/*
2233
 * Constructs a spanning tree with tight edges and adjusted the input node's
2234
 * ranks to achieve this. A tight edge is one that is has a length that matches
2235
 * its "minlen" attribute.
2236
 *
2237
 * The basic structure for this function is derived from Gansner, et al., "A
2238
 * Technique for Drawing Directed Graphs."
2239
 *
2240
 * Pre-conditions:
2241
 *
2242
 *    1. Graph must be a DAG.
2243
 *    2. Graph must be connected.
2244
 *    3. Graph must have at least one node.
2245
 *    5. Graph nodes must have been previously assigned a "rank" property that
2246
 *       respects the "minlen" property of incident edges.
2247
 *    6. Graph edges must have a "minlen" property.
2248
 *
2249
 * Post-conditions:
2250
 *
2251
 *    - Graph nodes will have their rank adjusted to ensure that all edges are
2252
 *      tight.
2253
 *
2254
 * Returns a tree (undirected graph) that is constructed using only "tight"
2255
 * edges.
2256
 */
2257
function feasibleTree(g) {
2258
  var t = new Graph({ directed: false });
2259

    
2260
  // Choose arbitrary node from which to start our tree
2261
  var start = g.nodes()[0],
2262
      size = g.nodeCount();
2263
  t.setNode(start, {});
2264

    
2265
  var edge, delta;
2266
  while (tightTree(t, g) < size) {
2267
    edge = findMinSlackEdge(t, g);
2268
    delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);
2269
    shiftRanks(t, g, delta);
2270
  }
2271

    
2272
  return t;
2273
}
2274

    
2275
/*
2276
 * Finds a maximal tree of tight edges and returns the number of nodes in the
2277
 * tree.
2278
 */
2279
function tightTree(t, g) {
2280
  function dfs(v) {
2281
    _.each(g.nodeEdges(v), function(e) {
2282
      var edgeV = e.v,
2283
          w = (v === edgeV) ? e.w : edgeV;
2284
      if (!t.hasNode(w) && !slack(g, e)) {
2285
        t.setNode(w, {});
2286
        t.setEdge(v, w, {});
2287
        dfs(w);
2288
      }
2289
    });
2290
  }
2291

    
2292
  _.each(t.nodes(), dfs);
2293
  return t.nodeCount();
2294
}
2295

    
2296
/*
2297
 * Finds the edge with the smallest slack that is incident on tree and returns
2298
 * it.
2299
 */
2300
function findMinSlackEdge(t, g) {
2301
  return _.min(g.edges(), function(e) {
2302
    if (t.hasNode(e.v) !== t.hasNode(e.w)) {
2303
      return slack(g, e);
2304
    }
2305
  });
2306
}
2307

    
2308
function shiftRanks(t, g, delta) {
2309
  _.each(t.nodes(), function(v) {
2310
    g.node(v).rank += delta;
2311
  });
2312
}
2313

    
2314
},{"../graphlib":7,"../lodash":10,"./util":28}],26:[function(require,module,exports){
2315
"use strict";
2316

    
2317
var rankUtil = require("./util"),
2318
    longestPath = rankUtil.longestPath,
2319
    feasibleTree = require("./feasible-tree"),
2320
    networkSimplex = require("./network-simplex");
2321

    
2322
module.exports = rank;
2323

    
2324
/*
2325
 * Assigns a rank to each node in the input graph that respects the "minlen"
2326
 * constraint specified on edges between nodes.
2327
 *
2328
 * This basic structure is derived from Gansner, et al., "A Technique for
2329
 * Drawing Directed Graphs."
2330
 *
2331
 * Pre-conditions:
2332
 *
2333
 *    1. Graph must be a connected DAG
2334
 *    2. Graph nodes must be objects
2335
 *    3. Graph edges must have "weight" and "minlen" attributes
2336
 *
2337
 * Post-conditions:
2338
 *
2339
 *    1. Graph nodes will have a "rank" attribute based on the results of the
2340
 *       algorithm. Ranks can start at any index (including negative), we'll
2341
 *       fix them up later.
2342
 */
2343
function rank(g) {
2344
  switch(g.graph().ranker) {
2345
    case "network-simplex": networkSimplexRanker(g); break;
2346
    case "tight-tree": tightTreeRanker(g); break;
2347
    case "longest-path": longestPathRanker(g); break;
2348
    default: networkSimplexRanker(g);
2349
  }
2350
}
2351

    
2352
// A fast and simple ranker, but results are far from optimal.
2353
var longestPathRanker = longestPath;
2354

    
2355
function tightTreeRanker(g) {
2356
  longestPath(g);
2357
  feasibleTree(g);
2358
}
2359

    
2360
function networkSimplexRanker(g) {
2361
  networkSimplex(g);
2362
}
2363

    
2364
},{"./feasible-tree":25,"./network-simplex":27,"./util":28}],27:[function(require,module,exports){
2365
"use strict";
2366

    
2367
var _ = require("../lodash"),
2368
    feasibleTree = require("./feasible-tree"),
2369
    slack = require("./util").slack,
2370
    initRank = require("./util").longestPath,
2371
    preorder = require("../graphlib").alg.preorder,
2372
    postorder = require("../graphlib").alg.postorder,
2373
    simplify = require("../util").simplify;
2374

    
2375
module.exports = networkSimplex;
2376

    
2377
// Expose some internals for testing purposes
2378
networkSimplex.initLowLimValues = initLowLimValues;
2379
networkSimplex.initCutValues = initCutValues;
2380
networkSimplex.calcCutValue = calcCutValue;
2381
networkSimplex.leaveEdge = leaveEdge;
2382
networkSimplex.enterEdge = enterEdge;
2383
networkSimplex.exchangeEdges = exchangeEdges;
2384

    
2385
/*
2386
 * The network simplex algorithm assigns ranks to each node in the input graph
2387
 * and iteratively improves the ranking to reduce the length of edges.
2388
 *
2389
 * Preconditions:
2390
 *
2391
 *    1. The input graph must be a DAG.
2392
 *    2. All nodes in the graph must have an object value.
2393
 *    3. All edges in the graph must have "minlen" and "weight" attributes.
2394
 *
2395
 * Postconditions:
2396
 *
2397
 *    1. All nodes in the graph will have an assigned "rank" attribute that has
2398
 *       been optimized by the network simplex algorithm. Ranks start at 0.
2399
 *
2400
 *
2401
 * A rough sketch of the algorithm is as follows:
2402
 *
2403
 *    1. Assign initial ranks to each node. We use the longest path algorithm,
2404
 *       which assigns ranks to the lowest position possible. In general this
2405
 *       leads to very wide bottom ranks and unnecessarily long edges.
2406
 *    2. Construct a feasible tight tree. A tight tree is one such that all
2407
 *       edges in the tree have no slack (difference between length of edge
2408
 *       and minlen for the edge). This by itself greatly improves the assigned
2409
 *       rankings by shorting edges.
2410
 *    3. Iteratively find edges that have negative cut values. Generally a
2411
 *       negative cut value indicates that the edge could be removed and a new
2412
 *       tree edge could be added to produce a more compact graph.
2413
 *
2414
 * Much of the algorithms here are derived from Gansner, et al., "A Technique
2415
 * for Drawing Directed Graphs." The structure of the file roughly follows the
2416
 * structure of the overall algorithm.
2417
 */
2418
function networkSimplex(g) {
2419
  g = simplify(g);
2420
  initRank(g);
2421
  var t = feasibleTree(g);
2422
  initLowLimValues(t);
2423
  initCutValues(t, g);
2424

    
2425
  var e, f;
2426
  while ((e = leaveEdge(t))) {
2427
    f = enterEdge(t, g, e);
2428
    exchangeEdges(t, g, e, f);
2429
  }
2430
}
2431

    
2432
/*
2433
 * Initializes cut values for all edges in the tree.
2434
 */
2435
function initCutValues(t, g) {
2436
  var vs = postorder(t, t.nodes());
2437
  vs = vs.slice(0, vs.length - 1);
2438
  _.each(vs, function(v) {
2439
    assignCutValue(t, g, v);
2440
  });
2441
}
2442

    
2443
function assignCutValue(t, g, child) {
2444
  var childLab = t.node(child),
2445
      parent = childLab.parent;
2446
  t.edge(child, parent).cutvalue = calcCutValue(t, g, child);
2447
}
2448

    
2449
/*
2450
 * Given the tight tree, its graph, and a child in the graph calculate and
2451
 * return the cut value for the edge between the child and its parent.
2452
 */
2453
function calcCutValue(t, g, child) {
2454
  var childLab = t.node(child),
2455
      parent = childLab.parent,
2456
      // True if the child is on the tail end of the edge in the directed graph
2457
      childIsTail = true,
2458
      // The graph's view of the tree edge we're inspecting
2459
      graphEdge = g.edge(child, parent),
2460
      // The accumulated cut value for the edge between this node and its parent
2461
      cutValue = 0;
2462

    
2463
  if (!graphEdge) {
2464
    childIsTail = false;
2465
    graphEdge = g.edge(parent, child);
2466
  }
2467

    
2468
  cutValue = graphEdge.weight;
2469

    
2470
  _.each(g.nodeEdges(child), function(e) {
2471
    var isOutEdge = e.v === child,
2472
        other = isOutEdge ? e.w : e.v;
2473

    
2474
    if (other !== parent) {
2475
      var pointsToHead = isOutEdge === childIsTail,
2476
          otherWeight = g.edge(e).weight;
2477

    
2478
      cutValue += pointsToHead ? otherWeight : -otherWeight;
2479
      if (isTreeEdge(t, child, other)) {
2480
        var otherCutValue = t.edge(child, other).cutvalue;
2481
        cutValue += pointsToHead ? -otherCutValue : otherCutValue;
2482
      }
2483
    }
2484
  });
2485

    
2486
  return cutValue;
2487
}
2488

    
2489
function initLowLimValues(tree, root) {
2490
  if (arguments.length < 2) {
2491
    root = tree.nodes()[0];
2492
  }
2493
  dfsAssignLowLim(tree, {}, 1, root);
2494
}
2495

    
2496
function dfsAssignLowLim(tree, visited, nextLim, v, parent) {
2497
  var low = nextLim,
2498
      label = tree.node(v);
2499

    
2500
  visited[v] = true;
2501
  _.each(tree.neighbors(v), function(w) {
2502
    if (!_.has(visited, w)) {
2503
      nextLim = dfsAssignLowLim(tree, visited, nextLim, w, v);
2504
    }
2505
  });
2506

    
2507
  label.low = low;
2508
  label.lim = nextLim++;
2509
  if (parent) {
2510
    label.parent = parent;
2511
  } else {
2512
    // TODO should be able to remove this when we incrementally update low lim
2513
    delete label.parent;
2514
  }
2515

    
2516
  return nextLim;
2517
}
2518

    
2519
function leaveEdge(tree) {
2520
  return _.find(tree.edges(), function(e) {
2521
    return tree.edge(e).cutvalue < 0;
2522
  });
2523
}
2524

    
2525
function enterEdge(t, g, edge) {
2526
  var v = edge.v,
2527
      w = edge.w;
2528

    
2529
  // For the rest of this function we assume that v is the tail and w is the
2530
  // head, so if we don't have this edge in the graph we should flip it to
2531
  // match the correct orientation.
2532
  if (!g.hasEdge(v, w)) {
2533
    v = edge.w;
2534
    w = edge.v;
2535
  }
2536

    
2537
  var vLabel = t.node(v),
2538
      wLabel = t.node(w),
2539
      tailLabel = vLabel,
2540
      flip = false;
2541

    
2542
  // If the root is in the tail of the edge then we need to flip the logic that
2543
  // checks for the head and tail nodes in the candidates function below.
2544
  if (vLabel.lim > wLabel.lim) {
2545
    tailLabel = wLabel;
2546
    flip = true;
2547
  }
2548

    
2549
  var candidates = _.filter(g.edges(), function(edge) {
2550
    return flip === isDescendant(t, t.node(edge.v), tailLabel) &&
2551
           flip !== isDescendant(t, t.node(edge.w), tailLabel);
2552
  });
2553

    
2554
  return _.min(candidates, function(edge) { return slack(g, edge); });
2555
}
2556

    
2557
function exchangeEdges(t, g, e, f) {
2558
  var v = e.v,
2559
      w = e.w;
2560
  t.removeEdge(v, w);
2561
  t.setEdge(f.v, f.w, {});
2562
  initLowLimValues(t);
2563
  initCutValues(t, g);
2564
  updateRanks(t, g);
2565
}
2566

    
2567
function updateRanks(t, g) {
2568
  var root = _.find(t.nodes(), function(v) { return !g.node(v).parent; }),
2569
      vs = preorder(t, root);
2570
  vs = vs.slice(1);
2571
  _.each(vs, function(v) {
2572
    var parent = t.node(v).parent,
2573
        edge = g.edge(v, parent),
2574
        flipped = false;
2575

    
2576
    if (!edge) {
2577
      edge = g.edge(parent, v);
2578
      flipped = true;
2579
    }
2580

    
2581
    g.node(v).rank = g.node(parent).rank + (flipped ? edge.minlen : -edge.minlen);
2582
  });
2583
}
2584

    
2585
/*
2586
 * Returns true if the edge is in the tree.
2587
 */
2588
function isTreeEdge(tree, u, v) {
2589
  return tree.hasEdge(u, v);
2590
}
2591

    
2592
/*
2593
 * Returns true if the specified node is descendant of the root node per the
2594
 * assigned low and lim attributes in the tree.
2595
 */
2596
function isDescendant(tree, vLabel, rootLabel) {
2597
  return rootLabel.low <= vLabel.lim && vLabel.lim <= rootLabel.lim;
2598
}
2599

    
2600
},{"../graphlib":7,"../lodash":10,"../util":29,"./feasible-tree":25,"./util":28}],28:[function(require,module,exports){
2601
"use strict";
2602

    
2603
var _ = require("../lodash");
2604

    
2605
module.exports = {
2606
  longestPath: longestPath,
2607
  slack: slack
2608
};
2609

    
2610
/*
2611
 * Initializes ranks for the input graph using the longest path algorithm. This
2612
 * algorithm scales well and is fast in practice, it yields rather poor
2613
 * solutions. Nodes are pushed to the lowest layer possible, leaving the bottom
2614
 * ranks wide and leaving edges longer than necessary. However, due to its
2615
 * speed, this algorithm is good for getting an initial ranking that can be fed
2616
 * into other algorithms.
2617
 *
2618
 * This algorithm does not normalize layers because it will be used by other
2619
 * algorithms in most cases. If using this algorithm directly, be sure to
2620
 * run normalize at the end.
2621
 *
2622
 * Pre-conditions:
2623
 *
2624
 *    1. Input graph is a DAG.
2625
 *    2. Input graph node labels can be assigned properties.
2626
 *
2627
 * Post-conditions:
2628
 *
2629
 *    1. Each node will be assign an (unnormalized) "rank" property.
2630
 */
2631
function longestPath(g) {
2632
  var visited = {};
2633

    
2634
  function dfs(v) {
2635
    var label = g.node(v);
2636
    if (_.has(visited, v)) {
2637
      return label.rank;
2638
    }
2639
    visited[v] = true;
2640

    
2641
    var rank = _.min(_.map(g.outEdges(v), function(e) {
2642
      return dfs(e.w) - g.edge(e).minlen;
2643
    }));
2644

    
2645
    if (rank === Number.POSITIVE_INFINITY) {
2646
      rank = 0;
2647
    }
2648

    
2649
    return (label.rank = rank);
2650
  }
2651

    
2652
  _.each(g.sources(), dfs);
2653
}
2654

    
2655
/*
2656
 * Returns the amount of slack for the given edge. The slack is defined as the
2657
 * difference between the length of the edge and its minimum length.
2658
 */
2659
function slack(g, e) {
2660
  return g.node(e.w).rank - g.node(e.v).rank - g.edge(e).minlen;
2661
}
2662

    
2663
},{"../lodash":10}],29:[function(require,module,exports){
2664
"use strict";
2665

    
2666
var _ = require("./lodash"),
2667
    Graph = require("./graphlib").Graph;
2668

    
2669
module.exports = {
2670
  addDummyNode: addDummyNode,
2671
  simplify: simplify,
2672
  asNonCompoundGraph: asNonCompoundGraph,
2673
  successorWeights: successorWeights,
2674
  predecessorWeights: predecessorWeights,
2675
  intersectRect: intersectRect,
2676
  buildLayerMatrix: buildLayerMatrix,
2677
  normalizeRanks: normalizeRanks,
2678
  removeEmptyRanks: removeEmptyRanks,
2679
  addBorderNode: addBorderNode,
2680
  maxRank: maxRank,
2681
  partition: partition,
2682
  time: time,
2683
  notime: notime
2684
};
2685

    
2686
/*
2687
 * Adds a dummy node to the graph and return v.
2688
 */
2689
function addDummyNode(g, type, attrs, name) {
2690
  var v;
2691
  do {
2692
    v = _.uniqueId(name);
2693
  } while (g.hasNode(v));
2694

    
2695
  attrs.dummy = type;
2696
  g.setNode(v, attrs);
2697
  return v;
2698
}
2699

    
2700
/*
2701
 * Returns a new graph with only simple edges. Handles aggregation of data
2702
 * associated with multi-edges.
2703
 */
2704
function simplify(g) {
2705
  var simplified = new Graph().setGraph(g.graph());
2706
  _.each(g.nodes(), function(v) { simplified.setNode(v, g.node(v)); });
2707
  _.each(g.edges(), function(e) {
2708
    var simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 },
2709
        label = g.edge(e);
2710
    simplified.setEdge(e.v, e.w, {
2711
      weight: simpleLabel.weight + label.weight,
2712
      minlen: Math.max(simpleLabel.minlen, label.minlen)
2713
    });
2714
  });
2715
  return simplified;
2716
}
2717

    
2718
function asNonCompoundGraph(g) {
2719
  var simplified = new Graph({ multigraph: g.isMultigraph() }).setGraph(g.graph());
2720
  _.each(g.nodes(), function(v) {
2721
    if (!g.children(v).length) {
2722
      simplified.setNode(v, g.node(v));
2723
    }
2724
  });
2725
  _.each(g.edges(), function(e) {
2726
    simplified.setEdge(e, g.edge(e));
2727
  });
2728
  return simplified;
2729
}
2730

    
2731
function successorWeights(g) {
2732
  var weightMap = _.map(g.nodes(), function(v) {
2733
    var sucs = {};
2734
    _.each(g.outEdges(v), function(e) {
2735
      sucs[e.w] = (sucs[e.w] || 0) + g.edge(e).weight;
2736
    });
2737
    return sucs;
2738
  });
2739
  return _.zipObject(g.nodes(), weightMap);
2740
}
2741

    
2742
function predecessorWeights(g) {
2743
  var weightMap = _.map(g.nodes(), function(v) {
2744
    var preds = {};
2745
    _.each(g.inEdges(v), function(e) {
2746
      preds[e.v] = (preds[e.v] || 0) + g.edge(e).weight;
2747
    });
2748
    return preds;
2749
  });
2750
  return _.zipObject(g.nodes(), weightMap);
2751
}
2752

    
2753
/*
2754
 * Finds where a line starting at point ({x, y}) would intersect a rectangle
2755
 * ({x, y, width, height}) if it were pointing at the rectangle's center.
2756
 */
2757
function intersectRect(rect, point) {
2758
  var x = rect.x;
2759
  var y = rect.y;
2760

    
2761
  // Rectangle intersection algorithm from:
2762
  // http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
2763
  var dx = point.x - x;
2764
  var dy = point.y - y;
2765
  var w = rect.width / 2;
2766
  var h = rect.height / 2;
2767

    
2768
  if (!dx && !dy) {
2769
    throw new Error("Not possible to find intersection inside of the rectangle");
2770
  }
2771

    
2772
  var sx, sy;
2773
  if (Math.abs(dy) * w > Math.abs(dx) * h) {
2774
    // Intersection is top or bottom of rect.
2775
    if (dy < 0) {
2776
      h = -h;
2777
    }
2778
    sx = h * dx / dy;
2779
    sy = h;
2780
  } else {
2781
    // Intersection is left or right of rect.
2782
    if (dx < 0) {
2783
      w = -w;
2784
    }
2785
    sx = w;
2786
    sy = w * dy / dx;
2787
  }
2788

    
2789
  return { x: x + sx, y: y + sy };
2790
}
2791

    
2792
/*
2793
 * Given a DAG with each node assigned "rank" and "order" properties, this
2794
 * function will produce a matrix with the ids of each node.
2795
 */
2796
function buildLayerMatrix(g) {
2797
  var layering = _.map(_.range(maxRank(g) + 1), function() { return []; });
2798
  _.each(g.nodes(), function(v) {
2799
    var node = g.node(v),
2800
        rank = node.rank;
2801
    if (!_.isUndefined(rank)) {
2802
      layering[rank][node.order] = v;
2803
    }
2804
  });
2805
  return layering;
2806
}
2807

    
2808
/*
2809
 * Adjusts the ranks for all nodes in the graph such that all nodes v have
2810
 * rank(v) >= 0 and at least one node w has rank(w) = 0.
2811
 */
2812
function normalizeRanks(g) {
2813
  var min = _.min(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
2814
  _.each(g.nodes(), function(v) {
2815
    var node = g.node(v);
2816
    if (_.has(node, "rank")) {
2817
      node.rank -= min;
2818
    }
2819
  });
2820
}
2821

    
2822
function removeEmptyRanks(g) {
2823
  // Ranks may not start at 0, so we need to offset them
2824
  var offset = _.min(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
2825

    
2826
  var layers = [];
2827
  _.each(g.nodes(), function(v) {
2828
    var rank = g.node(v).rank - offset;
2829
    if (!_.has(layers, rank)) {
2830
      layers[rank] = [];
2831
    }
2832
    layers[rank].push(v);
2833
  });
2834

    
2835
  var delta = 0,
2836
      nodeRankFactor = g.graph().nodeRankFactor;
2837
  _.each(layers, function(vs, i) {
2838
    if (_.isUndefined(vs) && i % nodeRankFactor !== 0) {
2839
      --delta;
2840
    } else if (delta) {
2841
      _.each(vs, function(v) { g.node(v).rank += delta; });
2842
    }
2843
  });
2844
}
2845

    
2846
function addBorderNode(g, prefix, rank, order) {
2847
  var node = {
2848
    width: 0,
2849
    height: 0
2850
  };
2851
  if (arguments.length >= 4) {
2852
    node.rank = rank;
2853
    node.order = order;
2854
  }
2855
  return addDummyNode(g, "border", node, prefix);
2856
}
2857

    
2858
function maxRank(g) {
2859
  return _.max(_.map(g.nodes(), function(v) {
2860
    var rank = g.node(v).rank;
2861
    if (!_.isUndefined(rank)) {
2862
      return rank;
2863
    }
2864
  }));
2865
}
2866

    
2867
/*
2868
 * Partition a collection into two groups: `lhs` and `rhs`. If the supplied
2869
 * function returns true for an entry it goes into `lhs`. Otherwise it goes
2870
 * into `rhs.
2871
 */
2872
function partition(collection, fn) {
2873
  var result = { lhs: [], rhs: [] };
2874
  _.each(collection, function(value) {
2875
    if (fn(value)) {
2876
      result.lhs.push(value);
2877
    } else {
2878
      result.rhs.push(value);
2879
    }
2880
  });
2881
  return result;
2882
}
2883

    
2884
/*
2885
 * Returns a new function that wraps `fn` with a timer. The wrapper logs the
2886
 * time it takes to execute the function.
2887
 */
2888
function time(name, fn) {
2889
  var start = _.now();
2890
  try {
2891
    return fn();
2892
  } finally {
2893
    console.log(name + " time: " + (_.now() - start) + "ms");
2894
  }
2895
}
2896

    
2897
function notime(name, fn) {
2898
  return fn();
2899
}
2900

    
2901
},{"./graphlib":7,"./lodash":10}],30:[function(require,module,exports){
2902
module.exports = "0.6.4";
2903

    
2904
},{}],31:[function(require,module,exports){
2905
/**
2906
 * Copyright (c) 2014, Chris Pettitt
2907
 * All rights reserved.
2908
 *
2909
 * Redistribution and use in source and binary forms, with or without
2910
 * modification, are permitted provided that the following conditions are met:
2911
 *
2912
 * 1. Redistributions of source code must retain the above copyright notice, this
2913
 * list of conditions and the following disclaimer.
2914
 *
2915
 * 2. Redistributions in binary form must reproduce the above copyright notice,
2916
 * this list of conditions and the following disclaimer in the documentation
2917
 * and/or other materials provided with the distribution.
2918
 *
2919
 * 3. Neither the name of the copyright holder nor the names of its contributors
2920
 * may be used to endorse or promote products derived from this software without
2921
 * specific prior written permission.
2922
 *
2923
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2924
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2925
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2926
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2927
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2928
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2929
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2930
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2931
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2932
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2933
 */
2934

    
2935
var lib = require("./lib");
2936

    
2937
module.exports = {
2938
  Graph: lib.Graph,
2939
  json: require("./lib/json"),
2940
  alg: require("./lib/alg"),
2941
  version: lib.version
2942
};
2943

    
2944
},{"./lib":47,"./lib/alg":38,"./lib/json":48}],32:[function(require,module,exports){
2945
var _ = require("../lodash");
2946

    
2947
module.exports = components;
2948

    
2949
function components(g) {
2950
  var visited = {},
2951
      cmpts = [],
2952
      cmpt;
2953

    
2954
  function dfs(v) {
2955
    if (_.has(visited, v)) return;
2956
    visited[v] = true;
2957
    cmpt.push(v);
2958
    _.each(g.successors(v), dfs);
2959
    _.each(g.predecessors(v), dfs);
2960
  }
2961

    
2962
  _.each(g.nodes(), function(v) {
2963
    cmpt = [];
2964
    dfs(v);
2965
    if (cmpt.length) {
2966
      cmpts.push(cmpt);
2967
    }
2968
  });
2969

    
2970
  return cmpts;
2971
}
2972

    
2973
},{"../lodash":49}],33:[function(require,module,exports){
2974
var _ = require("../lodash");
2975

    
2976
module.exports = dfs;
2977

    
2978
/*
2979
 * A helper that preforms a pre- or post-order traversal on the input graph
2980
 * and returns the nodes in the order they were visited. This algorithm treats
2981
 * the input as undirected.
2982
 *
2983
 * Order must be one of "pre" or "post".
2984
 */
2985
function dfs(g, vs, order) {
2986
  if (!_.isArray(vs)) {
2987
    vs = [vs];
2988
  }
2989

    
2990
  var acc = [],
2991
      visited = {};
2992
  _.each(vs, function(v) {
2993
    if (!g.hasNode(v)) {
2994
      throw new Error("Graph does not have node: " + v);
2995
    }
2996

    
2997
    doDfs(g, v, order === "post", visited, acc);
2998
  });
2999
  return acc;
3000
}
3001

    
3002
function doDfs(g, v, postorder, visited, acc) {
3003
  if (!_.has(visited, v)) {
3004
    visited[v] = true;
3005

    
3006
    if (!postorder) { acc.push(v); }
3007
    _.each(g.neighbors(v), function(w) {
3008
      doDfs(g, w, postorder, visited, acc);
3009
    });
3010
    if (postorder) { acc.push(v); }
3011
  }
3012
}
3013

    
3014
},{"../lodash":49}],34:[function(require,module,exports){
3015
var dijkstra = require("./dijkstra"),
3016
    _ = require("../lodash");
3017

    
3018
module.exports = dijkstraAll;
3019

    
3020
function dijkstraAll(g, weightFunc, edgeFunc) {
3021
  return _.transform(g.nodes(), function(acc, v) {
3022
    acc[v] = dijkstra(g, v, weightFunc, edgeFunc);
3023
  }, {});
3024
}
3025

    
3026
},{"../lodash":49,"./dijkstra":35}],35:[function(require,module,exports){
3027
var _ = require("../lodash"),
3028
    PriorityQueue = require("../data/priority-queue");
3029

    
3030
module.exports = dijkstra;
3031

    
3032
var DEFAULT_WEIGHT_FUNC = _.constant(1);
3033

    
3034
function dijkstra(g, source, weightFn, edgeFn) {
3035
  return runDijkstra(g, String(source),
3036
                     weightFn || DEFAULT_WEIGHT_FUNC,
3037
                     edgeFn || function(v) { return g.outEdges(v); });
3038
}
3039

    
3040
function runDijkstra(g, source, weightFn, edgeFn) {
3041
  var results = {},
3042
      pq = new PriorityQueue(),
3043
      v, vEntry;
3044

    
3045
  var updateNeighbors = function(edge) {
3046
    var w = edge.v !== v ? edge.v : edge.w,
3047
        wEntry = results[w],
3048
        weight = weightFn(edge),
3049
        distance = vEntry.distance + weight;
3050

    
3051
    if (weight < 0) {
3052
      throw new Error("dijkstra does not allow negative edge weights. " +
3053
                      "Bad edge: " + edge + " Weight: " + weight);
3054
    }
3055

    
3056
    if (distance < wEntry.distance) {
3057
      wEntry.distance = distance;
3058
      wEntry.predecessor = v;
3059
      pq.decrease(w, distance);
3060
    }
3061
  };
3062

    
3063
  g.nodes().forEach(function(v) {
3064
    var distance = v === source ? 0 : Number.POSITIVE_INFINITY;
3065
    results[v] = { distance: distance };
3066
    pq.add(v, distance);
3067
  });
3068

    
3069
  while (pq.size() > 0) {
3070
    v = pq.removeMin();
3071
    vEntry = results[v];
3072
    if (vEntry.distance === Number.POSITIVE_INFINITY) {
3073
      break;
3074
    }
3075

    
3076
    edgeFn(v).forEach(updateNeighbors);
3077
  }
3078

    
3079
  return results;
3080
}
3081

    
3082
},{"../data/priority-queue":45,"../lodash":49}],36:[function(require,module,exports){
3083
var _ = require("../lodash"),
3084
    tarjan = require("./tarjan");
3085

    
3086
module.exports = findCycles;
3087

    
3088
function findCycles(g) {
3089
  return _.filter(tarjan(g), function(cmpt) { return cmpt.length > 1; });
3090
}
3091

    
3092
},{"../lodash":49,"./tarjan":43}],37:[function(require,module,exports){
3093
var _ = require("../lodash");
3094

    
3095
module.exports = floydWarshall;
3096

    
3097
var DEFAULT_WEIGHT_FUNC = _.constant(1);
3098

    
3099
function floydWarshall(g, weightFn, edgeFn) {
3100
  return runFloydWarshall(g,
3101
                          weightFn || DEFAULT_WEIGHT_FUNC,
3102
                          edgeFn || function(v) { return g.outEdges(v); });
3103
}
3104

    
3105
function runFloydWarshall(g, weightFn, edgeFn) {
3106
  var results = {},
3107
      nodes = g.nodes();
3108

    
3109
  nodes.forEach(function(v) {
3110
    results[v] = {};
3111
    results[v][v] = { distance: 0 };
3112
    nodes.forEach(function(w) {
3113
      if (v !== w) {
3114
        results[v][w] = { distance: Number.POSITIVE_INFINITY };
3115
      }
3116
    });
3117
    edgeFn(v).forEach(function(edge) {
3118
      var w = edge.v === v ? edge.w : edge.v,
3119
          d = weightFn(edge);
3120
      results[v][w] = { distance: d, predecessor: v };
3121
    });
3122
  });
3123

    
3124
  nodes.forEach(function(k) {
3125
    var rowK = results[k];
3126
    nodes.forEach(function(i) {
3127
      var rowI = results[i];
3128
      nodes.forEach(function(j) {
3129
        var ik = rowI[k];
3130
        var kj = rowK[j];
3131
        var ij = rowI[j];
3132
        var altDistance = ik.distance + kj.distance;
3133
        if (altDistance < ij.distance) {
3134
          ij.distance = altDistance;
3135
          ij.predecessor = kj.predecessor;
3136
        }
3137
      });
3138
    });
3139
  });
3140

    
3141
  return results;
3142
}
3143

    
3144
},{"../lodash":49}],38:[function(require,module,exports){
3145
module.exports = {
3146
  components: require("./components"),
3147
  dijkstra: require("./dijkstra"),
3148
  dijkstraAll: require("./dijkstra-all"),
3149
  findCycles: require("./find-cycles"),
3150
  floydWarshall: require("./floyd-warshall"),
3151
  isAcyclic: require("./is-acyclic"),
3152
  postorder: require("./postorder"),
3153
  preorder: require("./preorder"),
3154
  prim: require("./prim"),
3155
  tarjan: require("./tarjan"),
3156
  topsort: require("./topsort")
3157
};
3158

    
3159
},{"./components":32,"./dijkstra":35,"./dijkstra-all":34,"./find-cycles":36,"./floyd-warshall":37,"./is-acyclic":39,"./postorder":40,"./preorder":41,"./prim":42,"./tarjan":43,"./topsort":44}],39:[function(require,module,exports){
3160
var topsort = require("./topsort");
3161

    
3162
module.exports = isAcyclic;
3163

    
3164
function isAcyclic(g) {
3165
  try {
3166
    topsort(g);
3167
  } catch (e) {
3168
    if (e instanceof topsort.CycleException) {
3169
      return false;
3170
    }
3171
    throw e;
3172
  }
3173
  return true;
3174
}
3175

    
3176
},{"./topsort":44}],40:[function(require,module,exports){
3177
var dfs = require("./dfs");
3178

    
3179
module.exports = postorder;
3180

    
3181
function postorder(g, vs) {
3182
  return dfs(g, vs, "post");
3183
}
3184

    
3185
},{"./dfs":33}],41:[function(require,module,exports){
3186
var dfs = require("./dfs");
3187

    
3188
module.exports = preorder;
3189

    
3190
function preorder(g, vs) {
3191
  return dfs(g, vs, "pre");
3192
}
3193

    
3194
},{"./dfs":33}],42:[function(require,module,exports){
3195
var _ = require("../lodash"),
3196
    Graph = require("../graph"),
3197
    PriorityQueue = require("../data/priority-queue");
3198

    
3199
module.exports = prim;
3200

    
3201
function prim(g, weightFunc) {
3202
  var result = new Graph(),
3203
      parents = {},
3204
      pq = new PriorityQueue(),
3205
      v;
3206

    
3207
  function updateNeighbors(edge) {
3208
    var w = edge.v === v ? edge.w : edge.v,
3209
        pri = pq.priority(w);
3210
    if (pri !== undefined) {
3211
      var edgeWeight = weightFunc(edge);
3212
      if (edgeWeight < pri) {
3213
        parents[w] = v;
3214
        pq.decrease(w, edgeWeight);
3215
      }
3216
    }
3217
  }
3218

    
3219
  if (g.nodeCount() === 0) {
3220
    return result;
3221
  }
3222

    
3223
  _.each(g.nodes(), function(v) {
3224
    pq.add(v, Number.POSITIVE_INFINITY);
3225
    result.setNode(v);
3226
  });
3227

    
3228
  // Start from an arbitrary node
3229
  pq.decrease(g.nodes()[0], 0);
3230

    
3231
  var init = false;
3232
  while (pq.size() > 0) {
3233
    v = pq.removeMin();
3234
    if (_.has(parents, v)) {
3235
      result.setEdge(v, parents[v]);
3236
    } else if (init) {
3237
      throw new Error("Input graph is not connected: " + g);
3238
    } else {
3239
      init = true;
3240
    }
3241

    
3242
    g.nodeEdges(v).forEach(updateNeighbors);
3243
  }
3244

    
3245
  return result;
3246
}
3247

    
3248
},{"../data/priority-queue":45,"../graph":46,"../lodash":49}],43:[function(require,module,exports){
3249
var _ = require("../lodash");
3250

    
3251
module.exports = tarjan;
3252

    
3253
function tarjan(g) {
3254
  var index = 0,
3255
      stack = [],
3256
      visited = {}, // node id -> { onStack, lowlink, index }
3257
      results = [];
3258

    
3259
  function dfs(v) {
3260
    var entry = visited[v] = {
3261
      onStack: true,
3262
      lowlink: index,
3263
      index: index++
3264
    };
3265
    stack.push(v);
3266

    
3267
    g.successors(v).forEach(function(w) {
3268
      if (!_.has(visited, w)) {
3269
        dfs(w);
3270
        entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink);
3271
      } else if (visited[w].onStack) {
3272
        entry.lowlink = Math.min(entry.lowlink, visited[w].index);
3273
      }
3274
    });
3275

    
3276
    if (entry.lowlink === entry.index) {
3277
      var cmpt = [],
3278
          w;
3279
      do {
3280
        w = stack.pop();
3281
        visited[w].onStack = false;
3282
        cmpt.push(w);
3283
      } while (v !== w);
3284
      results.push(cmpt);
3285
    }
3286
  }
3287

    
3288
  g.nodes().forEach(function(v) {
3289
    if (!_.has(visited, v)) {
3290
      dfs(v);
3291
    }
3292
  });
3293

    
3294
  return results;
3295
}
3296

    
3297
},{"../lodash":49}],44:[function(require,module,exports){
3298
var _ = require("../lodash");
3299

    
3300
module.exports = topsort;
3301
topsort.CycleException = CycleException;
3302

    
3303
function topsort(g) {
3304
  var visited = {},
3305
      stack = {},
3306
      results = [];
3307

    
3308
  function visit(node) {
3309
    if (_.has(stack, node)) {
3310
      throw new CycleException();
3311
    }
3312

    
3313
    if (!_.has(visited, node)) {
3314
      stack[node] = true;
3315
      visited[node] = true;
3316
      _.each(g.predecessors(node), visit);
3317
      delete stack[node];
3318
      results.push(node);
3319
    }
3320
  }
3321

    
3322
  _.each(g.sinks(), visit);
3323

    
3324
  if (_.size(visited) !== g.nodeCount()) {
3325
    throw new CycleException();
3326
  }
3327

    
3328
  return results;
3329
}
3330

    
3331
function CycleException() {}
3332

    
3333
},{"../lodash":49}],45:[function(require,module,exports){
3334
var _ = require("../lodash");
3335

    
3336
module.exports = PriorityQueue;
3337

    
3338
/**
3339
 * A min-priority queue data structure. This algorithm is derived from Cormen,
3340
 * et al., "Introduction to Algorithms". The basic idea of a min-priority
3341
 * queue is that you can efficiently (in O(1) time) get the smallest key in
3342
 * the queue. Adding and removing elements takes O(log n) time. A key can
3343
 * have its priority decreased in O(log n) time.
3344
 */
3345
function PriorityQueue() {
3346
  this._arr = [];
3347
  this._keyIndices = {};
3348
}
3349

    
3350
/**
3351
 * Returns the number of elements in the queue. Takes `O(1)` time.
3352
 */
3353
PriorityQueue.prototype.size = function() {
3354
  return this._arr.length;
3355
};
3356

    
3357
/**
3358
 * Returns the keys that are in the queue. Takes `O(n)` time.
3359
 */
3360
PriorityQueue.prototype.keys = function() {
3361
  return this._arr.map(function(x) { return x.key; });
3362
};
3363

    
3364
/**
3365
 * Returns `true` if **key** is in the queue and `false` if not.
3366
 */
3367
PriorityQueue.prototype.has = function(key) {
3368
  return _.has(this._keyIndices, key);
3369
};
3370

    
3371
/**
3372
 * Returns the priority for **key**. If **key** is not present in the queue
3373
 * then this function returns `undefined`. Takes `O(1)` time.
3374
 *
3375
 * @param {Object} key
3376
 */
3377
PriorityQueue.prototype.priority = function(key) {
3378
  var index = this._keyIndices[key];
3379
  if (index !== undefined) {
3380
    return this._arr[index].priority;
3381
  }
3382
};
3383

    
3384
/**
3385
 * Returns the key for the minimum element in this queue. If the queue is
3386
 * empty this function throws an Error. Takes `O(1)` time.
3387
 */
3388
PriorityQueue.prototype.min = function() {
3389
  if (this.size() === 0) {
3390
    throw new Error("Queue underflow");
3391
  }
3392
  return this._arr[0].key;
3393
};
3394

    
3395
/**
3396
 * Inserts a new key into the priority queue. If the key already exists in
3397
 * the queue this function returns `false`; otherwise it will return `true`.
3398
 * Takes `O(n)` time.
3399
 *
3400
 * @param {Object} key the key to add
3401
 * @param {Number} priority the initial priority for the key
3402
 */
3403
PriorityQueue.prototype.add = function(key, priority) {
3404
  var keyIndices = this._keyIndices;
3405
  key = String(key);
3406
  if (!_.has(keyIndices, key)) {
3407
    var arr = this._arr;
3408
    var index = arr.length;
3409
    keyIndices[key] = index;
3410
    arr.push({key: key, priority: priority});
3411
    this._decrease(index);
3412
    return true;
3413
  }
3414
  return false;
3415
};
3416

    
3417
/**
3418
 * Removes and returns the smallest key in the queue. Takes `O(log n)` time.
3419
 */
3420
PriorityQueue.prototype.removeMin = function() {
3421
  this._swap(0, this._arr.length - 1);
3422
  var min = this._arr.pop();
3423
  delete this._keyIndices[min.key];
3424
  this._heapify(0);
3425
  return min.key;
3426
};
3427

    
3428
/**
3429
 * Decreases the priority for **key** to **priority**. If the new priority is
3430
 * greater than the previous priority, this function will throw an Error.
3431
 *
3432
 * @param {Object} key the key for which to raise priority
3433
 * @param {Number} priority the new priority for the key
3434
 */
3435
PriorityQueue.prototype.decrease = function(key, priority) {
3436
  var index = this._keyIndices[key];
3437
  if (priority > this._arr[index].priority) {
3438
    throw new Error("New priority is greater than current priority. " +
3439
        "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority);
3440
  }
3441
  this._arr[index].priority = priority;
3442
  this._decrease(index);
3443
};
3444

    
3445
PriorityQueue.prototype._heapify = function(i) {
3446
  var arr = this._arr;
3447
  var l = 2 * i,
3448
      r = l + 1,
3449
      largest = i;
3450
  if (l < arr.length) {
3451
    largest = arr[l].priority < arr[largest].priority ? l : largest;
3452
    if (r < arr.length) {
3453
      largest = arr[r].priority < arr[largest].priority ? r : largest;
3454
    }
3455
    if (largest !== i) {
3456
      this._swap(i, largest);
3457
      this._heapify(largest);
3458
    }
3459
  }
3460
};
3461

    
3462
PriorityQueue.prototype._decrease = function(index) {
3463
  var arr = this._arr;
3464
  var priority = arr[index].priority;
3465
  var parent;
3466
  while (index !== 0) {
3467
    parent = index >> 1;
3468
    if (arr[parent].priority < priority) {
3469
      break;
3470
    }
3471
    this._swap(index, parent);
3472
    index = parent;
3473
  }
3474
};
3475

    
3476
PriorityQueue.prototype._swap = function(i, j) {
3477
  var arr = this._arr;
3478
  var keyIndices = this._keyIndices;
3479
  var origArrI = arr[i];
3480
  var origArrJ = arr[j];
3481
  arr[i] = origArrJ;
3482
  arr[j] = origArrI;
3483
  keyIndices[origArrJ.key] = i;
3484
  keyIndices[origArrI.key] = j;
3485
};
3486

    
3487
},{"../lodash":49}],46:[function(require,module,exports){
3488
"use strict";
3489

    
3490
var _ = require("./lodash");
3491

    
3492
module.exports = Graph;
3493

    
3494
var DEFAULT_EDGE_NAME = "\x00",
3495
    GRAPH_NODE = "\x00",
3496
    EDGE_KEY_DELIM = "\x01";
3497

    
3498
// Implementation notes:
3499
//
3500
//  * Node id query functions should return string ids for the nodes
3501
//  * Edge id query functions should return an "edgeObj", edge object, that is
3502
//    composed of enough information to uniquely identify an edge: {v, w, name}.
3503
//  * Internally we use an "edgeId", a stringified form of the edgeObj, to
3504
//    reference edges. This is because we need a performant way to look these
3505
//    edges up and, object properties, which have string keys, are the closest
3506
//    we're going to get to a performant hashtable in JavaScript.
3507

    
3508
function Graph(opts) {
3509
  this._isDirected = _.has(opts, "directed") ? opts.directed : true;
3510
  this._isMultigraph = _.has(opts, "multigraph") ? opts.multigraph : false;
3511
  this._isCompound = _.has(opts, "compound") ? opts.compound : false;
3512

    
3513
  // Label for the graph itself
3514
  this._label = undefined;
3515

    
3516
  // Defaults to be set when creating a new node
3517
  this._defaultNodeLabelFn = _.constant(undefined);
3518

    
3519
  // Defaults to be set when creating a new edge
3520
  this._defaultEdgeLabelFn = _.constant(undefined);
3521

    
3522
  // v -> label
3523
  this._nodes = {};
3524

    
3525
  if (this._isCompound) {
3526
    // v -> parent
3527
    this._parent = {};
3528

    
3529
    // v -> children
3530
    this._children = {};
3531
    this._children[GRAPH_NODE] = {};
3532
  }
3533

    
3534
  // v -> edgeObj
3535
  this._in = {};
3536

    
3537
  // u -> v -> Number
3538
  this._preds = {};
3539

    
3540
  // v -> edgeObj
3541
  this._out = {};
3542

    
3543
  // v -> w -> Number
3544
  this._sucs = {};
3545

    
3546
  // e -> edgeObj
3547
  this._edgeObjs = {};
3548

    
3549
  // e -> label
3550
  this._edgeLabels = {};
3551
}
3552

    
3553
/* Number of nodes in the graph. Should only be changed by the implementation. */
3554
Graph.prototype._nodeCount = 0;
3555

    
3556
/* Number of edges in the graph. Should only be changed by the implementation. */
3557
Graph.prototype._edgeCount = 0;
3558

    
3559

    
3560
/* === Graph functions ========= */
3561

    
3562
Graph.prototype.isDirected = function() {
3563
  return this._isDirected;
3564
};
3565

    
3566
Graph.prototype.isMultigraph = function() {
3567
  return this._isMultigraph;
3568
};
3569

    
3570
Graph.prototype.isCompound = function() {
3571
  return this._isCompound;
3572
};
3573

    
3574
Graph.prototype.setGraph = function(label) {
3575
  this._label = label;
3576
  return this;
3577
};
3578

    
3579
Graph.prototype.graph = function() {
3580
  return this._label;
3581
};
3582

    
3583

    
3584
/* === Node functions ========== */
3585

    
3586
Graph.prototype.setDefaultNodeLabel = function(newDefault) {
3587
  if (!_.isFunction(newDefault)) {
3588
    newDefault = _.constant(newDefault);
3589
  }
3590
  this._defaultNodeLabelFn = newDefault;
3591
  return this;
3592
};
3593

    
3594
Graph.prototype.nodeCount = function() {
3595
  return this._nodeCount;
3596
};
3597

    
3598
Graph.prototype.nodes = function() {
3599
  return _.keys(this._nodes);
3600
};
3601

    
3602
Graph.prototype.sources = function() {
3603
  return _.filter(this.nodes(), function(v) {
3604
    return _.isEmpty(this._in[v]);
3605
  }, this);
3606
};
3607

    
3608
Graph.prototype.sinks = function() {
3609
  return _.filter(this.nodes(), function(v) {
3610
    return _.isEmpty(this._out[v]);
3611
  }, this);
3612
};
3613

    
3614
Graph.prototype.setNodes = function(vs, value) {
3615
  var args = arguments;
3616
  _.each(vs, function(v) {
3617
    if (args.length > 1) {
3618
      this.setNode(v, value);
3619
    } else {
3620
      this.setNode(v);
3621
    }
3622
  }, this);
3623
  return this;
3624
};
3625

    
3626
Graph.prototype.setNode = function(v, value) {
3627
  if (_.has(this._nodes, v)) {
3628
    if (arguments.length > 1) {
3629
      this._nodes[v] = value;
3630
    }
3631
    return this;
3632
  }
3633

    
3634
  this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
3635
  if (this._isCompound) {
3636
    this._parent[v] = GRAPH_NODE;
3637
    this._children[v] = {};
3638
    this._children[GRAPH_NODE][v] = true;
3639
  }
3640
  this._in[v] = {};
3641
  this._preds[v] = {};
3642
  this._out[v] = {};
3643
  this._sucs[v] = {};
3644
  ++this._nodeCount;
3645
  return this;
3646
};
3647

    
3648
Graph.prototype.node = function(v) {
3649
  return this._nodes[v];
3650
};
3651

    
3652
Graph.prototype.hasNode = function(v) {
3653
  return _.has(this._nodes, v);
3654
};
3655

    
3656
Graph.prototype.removeNode =  function(v) {
3657
  var self = this;
3658
  if (_.has(this._nodes, v)) {
3659
    var removeEdge = function(e) { self.removeEdge(self._edgeObjs[e]); };
3660
    delete this._nodes[v];
3661
    if (this._isCompound) {
3662
      this._removeFromParentsChildList(v);
3663
      delete this._parent[v];
3664
      _.each(this.children(v), function(child) {
3665
        this.setParent(child);
3666
      }, this);
3667
      delete this._children[v];
3668
    }
3669
    _.each(_.keys(this._in[v]), removeEdge);
3670
    delete this._in[v];
3671
    delete this._preds[v];
3672
    _.each(_.keys(this._out[v]), removeEdge);
3673
    delete this._out[v];
3674
    delete this._sucs[v];
3675
    --this._nodeCount;
3676
  }
3677
  return this;
3678
};
3679

    
3680
Graph.prototype.setParent = function(v, parent) {
3681
  if (!this._isCompound) {
3682
    throw new Error("Cannot set parent in a non-compound graph");
3683
  }
3684

    
3685
  if (_.isUndefined(parent)) {
3686
    parent = GRAPH_NODE;
3687
  } else {
3688
    for (var ancestor = parent;
3689
         !_.isUndefined(ancestor);
3690
         ancestor = this.parent(ancestor)) {
3691
      if (ancestor === v) {
3692
        throw new Error("Setting " + parent+ " as parent of " + v +
3693
                        " would create create a cycle");
3694
      }
3695
    }
3696

    
3697
    this.setNode(parent);
3698
  }
3699

    
3700
  this.setNode(v);
3701
  this._removeFromParentsChildList(v);
3702
  this._parent[v] = parent;
3703
  this._children[parent][v] = true;
3704
  return this;
3705
};
3706

    
3707
Graph.prototype._removeFromParentsChildList = function(v) {
3708
  delete this._children[this._parent[v]][v];
3709
};
3710

    
3711
Graph.prototype.parent = function(v) {
3712
  if (this._isCompound) {
3713
    var parent = this._parent[v];
3714
    if (parent !== GRAPH_NODE) {
3715
      return parent;
3716
    }
3717
  }
3718
};
3719

    
3720
Graph.prototype.children = function(v) {
3721
  if (_.isUndefined(v)) {
3722
    v = GRAPH_NODE;
3723
  }
3724

    
3725
  if (this._isCompound) {
3726
    var children = this._children[v];
3727
    if (children) {
3728
      return _.keys(children);
3729
    }
3730
  } else if (v === GRAPH_NODE) {
3731
    return this.nodes();
3732
  } else if (this.hasNode(v)) {
3733
    return [];
3734
  }
3735
};
3736

    
3737
Graph.prototype.predecessors = function(v) {
3738
  var predsV = this._preds[v];
3739
  if (predsV) {
3740
    return _.keys(predsV);
3741
  }
3742
};
3743

    
3744
Graph.prototype.successors = function(v) {
3745
  var sucsV = this._sucs[v];
3746
  if (sucsV) {
3747
    return _.keys(sucsV);
3748
  }
3749
};
3750

    
3751
Graph.prototype.neighbors = function(v) {
3752
  var preds = this.predecessors(v);
3753
  if (preds) {
3754
    return _.union(preds, this.successors(v));
3755
  }
3756
};
3757

    
3758
/* === Edge functions ========== */
3759

    
3760
Graph.prototype.setDefaultEdgeLabel = function(newDefault) {
3761
  if (!_.isFunction(newDefault)) {
3762
    newDefault = _.constant(newDefault);
3763
  }
3764
  this._defaultEdgeLabelFn = newDefault;
3765
  return this;
3766
};
3767

    
3768
Graph.prototype.edgeCount = function() {
3769
  return this._edgeCount;
3770
};
3771

    
3772
Graph.prototype.edges = function() {
3773
  return _.values(this._edgeObjs);
3774
};
3775

    
3776
Graph.prototype.setPath = function(vs, value) {
3777
  var self = this,
3778
      args = arguments;
3779
  _.reduce(vs, function(v, w) {
3780
    if (args.length > 1) {
3781
      self.setEdge(v, w, value);
3782
    } else {
3783
      self.setEdge(v, w);
3784
    }
3785
    return w;
3786
  });
3787
  return this;
3788
};
3789

    
3790
/*
3791
 * setEdge(v, w, [value, [name]])
3792
 * setEdge({ v, w, [name] }, [value])
3793
 */
3794
Graph.prototype.setEdge = function() {
3795
  var v, w, name, value,
3796
      valueSpecified = false;
3797

    
3798
  if (_.isPlainObject(arguments[0])) {
3799
    v = arguments[0].v;
3800
    w = arguments[0].w;
3801
    name = arguments[0].name;
3802
    if (arguments.length === 2) {
3803
      value = arguments[1];
3804
      valueSpecified = true;
3805
    }
3806
  } else {
3807
    v = arguments[0];
3808
    w = arguments[1];
3809
    name = arguments[3];
3810
    if (arguments.length > 2) {
3811
      value = arguments[2];
3812
      valueSpecified = true;
3813
    }
3814
  }
3815

    
3816
  v = "" + v;
3817
  w = "" + w;
3818
  if (!_.isUndefined(name)) {
3819
    name = "" + name;
3820
  }
3821

    
3822
  var e = edgeArgsToId(this._isDirected, v, w, name);
3823
  if (_.has(this._edgeLabels, e)) {
3824
    if (valueSpecified) {
3825
      this._edgeLabels[e] = value;
3826
    }
3827
    return this;
3828
  }
3829

    
3830
  if (!_.isUndefined(name) && !this._isMultigraph) {
3831
    throw new Error("Cannot set a named edge when isMultigraph = false");
3832
  }
3833

    
3834
  // It didn't exist, so we need to create it.
3835
  // First ensure the nodes exist.
3836
  this.setNode(v);
3837
  this.setNode(w);
3838

    
3839
  this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name);
3840

    
3841
  var edgeObj = edgeArgsToObj(this._isDirected, v, w, name);
3842
  // Ensure we add undirected edges in a consistent way.
3843
  v = edgeObj.v;
3844
  w = edgeObj.w;
3845

    
3846
  Object.freeze(edgeObj);
3847
  this._edgeObjs[e] = edgeObj;
3848
  incrementOrInitEntry(this._preds[w], v);
3849
  incrementOrInitEntry(this._sucs[v], w);
3850
  this._in[w][e] = edgeObj;
3851
  this._out[v][e] = edgeObj;
3852
  this._edgeCount++;
3853
  return this;
3854
};
3855

    
3856
Graph.prototype.edge = function(v, w, name) {
3857
  var e = (arguments.length === 1
3858
            ? edgeObjToId(this._isDirected, arguments[0])
3859
            : edgeArgsToId(this._isDirected, v, w, name));
3860
  return this._edgeLabels[e];
3861
};
3862

    
3863
Graph.prototype.hasEdge = function(v, w, name) {
3864
  var e = (arguments.length === 1
3865
            ? edgeObjToId(this._isDirected, arguments[0])
3866
            : edgeArgsToId(this._isDirected, v, w, name));
3867
  return _.has(this._edgeLabels, e);
3868
};
3869

    
3870
Graph.prototype.removeEdge = function(v, w, name) {
3871
  var e = (arguments.length === 1
3872
            ? edgeObjToId(this._isDirected, arguments[0])
3873
            : edgeArgsToId(this._isDirected, v, w, name)),
3874
      edge = this._edgeObjs[e];
3875
  if (edge) {
3876
    v = edge.v;
3877
    w = edge.w;
3878
    delete this._edgeLabels[e];
3879
    delete this._edgeObjs[e];
3880
    decrementOrRemoveEntry(this._preds[w], v);
3881
    decrementOrRemoveEntry(this._sucs[v], w);
3882
    delete this._in[w][e];
3883
    delete this._out[v][e];
3884
    this._edgeCount--;
3885
  }
3886
  return this;
3887
};
3888

    
3889
Graph.prototype.inEdges = function(v, u) {
3890
  var inV = this._in[v];
3891
  if (inV) {
3892
    var edges = _.values(inV);
3893
    if (!u) {
3894
      return edges;
3895
    }
3896
    return _.filter(edges, function(edge) { return edge.v === u; });
3897
  }
3898
};
3899

    
3900
Graph.prototype.outEdges = function(v, w) {
3901
  var outV = this._out[v];
3902
  if (outV) {
3903
    var edges = _.values(outV);
3904
    if (!w) {
3905
      return edges;
3906
    }
3907
    return _.filter(edges, function(edge) { return edge.w === w; });
3908
  }
3909
};
3910

    
3911
Graph.prototype.nodeEdges = function(v, w) {
3912
  var inEdges = this.inEdges(v, w);
3913
  if (inEdges) {
3914
    return inEdges.concat(this.outEdges(v, w));
3915
  }
3916
};
3917

    
3918
function incrementOrInitEntry(map, k) {
3919
  if (_.has(map, k)) {
3920
    map[k]++;
3921
  } else {
3922
    map[k] = 1;
3923
  }
3924
}
3925

    
3926
function decrementOrRemoveEntry(map, k) {
3927
  if (!--map[k]) { delete map[k]; }
3928
}
3929

    
3930
function edgeArgsToId(isDirected, v, w, name) {
3931
  if (!isDirected && v > w) {
3932
    var tmp = v;
3933
    v = w;
3934
    w = tmp;
3935
  }
3936
  return v + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM +
3937
             (_.isUndefined(name) ? DEFAULT_EDGE_NAME : name);
3938
}
3939

    
3940
function edgeArgsToObj(isDirected, v, w, name) {
3941
  if (!isDirected && v > w) {
3942
    var tmp = v;
3943
    v = w;
3944
    w = tmp;
3945
  }
3946
  var edgeObj =  { v: v, w: w };
3947
  if (name) {
3948
    edgeObj.name = name;
3949
  }
3950
  return edgeObj;
3951
}
3952

    
3953
function edgeObjToId(isDirected, edgeObj) {
3954
  return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name);
3955
}
3956

    
3957
},{"./lodash":49}],47:[function(require,module,exports){
3958
// Includes only the "core" of graphlib
3959
module.exports = {
3960
  Graph: require("./graph"),
3961
  version: require("./version")
3962
};
3963

    
3964
},{"./graph":46,"./version":50}],48:[function(require,module,exports){
3965
var _ = require("./lodash"),
3966
    Graph = require("./graph");
3967

    
3968
module.exports = {
3969
  write: write,
3970
  read: read
3971
};
3972

    
3973
function write(g) {
3974
  var json = {
3975
    options: {
3976
      directed: g.isDirected(),
3977
      multigraph: g.isMultigraph(),
3978
      compound: g.isCompound()
3979
    },
3980
    nodes: writeNodes(g),
3981
    edges: writeEdges(g)
3982
  };
3983
  if (!_.isUndefined(g.graph())) {
3984
    json.value = _.clone(g.graph());
3985
  }
3986
  return json;
3987
}
3988

    
3989
function writeNodes(g) {
3990
  return _.map(g.nodes(), function(v) {
3991
    var nodeValue = g.node(v),
3992
        parent = g.parent(v),
3993
        node = { v: v };
3994
    if (!_.isUndefined(nodeValue)) {
3995
      node.value = nodeValue;
3996
    }
3997
    if (!_.isUndefined(parent)) {
3998
      node.parent = parent;
3999
    }
4000
    return node;
4001
  });
4002
}
4003

    
4004
function writeEdges(g) {
4005
  return _.map(g.edges(), function(e) {
4006
    var edgeValue = g.edge(e),
4007
        edge = { v: e.v, w: e.w };
4008
    if (!_.isUndefined(e.name)) {
4009
      edge.name = e.name;
4010
    }
4011
    if (!_.isUndefined(edgeValue)) {
4012
      edge.value = edgeValue;
4013
    }
4014
    return edge;
4015
  });
4016
}
4017

    
4018
function read(json) {
4019
  var g = new Graph(json.options).setGraph(json.value);
4020
  _.each(json.nodes, function(entry) {
4021
    g.setNode(entry.v, entry.value);
4022
    if (entry.parent) {
4023
      g.setParent(entry.v, entry.parent);
4024
    }
4025
  });
4026
  _.each(json.edges, function(entry) {
4027
    g.setEdge({ v: entry.v, w: entry.w, name: entry.name }, entry.value);
4028
  });
4029
  return g;
4030
}
4031

    
4032
},{"./graph":46,"./lodash":49}],49:[function(require,module,exports){
4033
module.exports=require(10)
4034
},{"/Users/cpettitt/projects/dagre/lib/lodash.js":10,"lodash":51}],50:[function(require,module,exports){
4035
module.exports = '1.0.1';
4036

    
4037
},{}],51:[function(require,module,exports){
4038
(function (global){
4039
/**
4040
 * @license
4041
 * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
4042
 * Build: `lodash modern -o ./dist/lodash.js`
4043
 * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
4044
 * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
4045
 * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
4046
 * Available under MIT license <http://lodash.com/license>
4047
 */
4048
;(function() {
4049

    
4050
  /** Used as a safe reference for `undefined` in pre ES5 environments */
4051
  var undefined;
4052

    
4053
  /** Used to pool arrays and objects used internally */
4054
  var arrayPool = [],
4055
      objectPool = [];
4056

    
4057
  /** Used to generate unique IDs */
4058
  var idCounter = 0;
4059

    
4060
  /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
4061
  var keyPrefix = +new Date + '';
4062

    
4063
  /** Used as the size when optimizations are enabled for large arrays */
4064
  var largeArraySize = 75;
4065

    
4066
  /** Used as the max size of the `arrayPool` and `objectPool` */
4067
  var maxPoolSize = 40;
4068

    
4069
  /** Used to detect and test whitespace */
4070
  var whitespace = (
4071
    // whitespace
4072
    ' \t\x0B\f\xA0\ufeff' +
4073

    
4074
    // line terminators
4075
    '\n\r\u2028\u2029' +
4076

    
4077
    // unicode category "Zs" space separators
4078
    '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
4079
  );
4080

    
4081
  /** Used to match empty string literals in compiled template source */
4082
  var reEmptyStringLeading = /\b__p \+= '';/g,
4083
      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
4084
      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
4085

    
4086
  /**
4087
   * Used to match ES6 template delimiters
4088
   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
4089
   */
4090
  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
4091

    
4092
  /** Used to match regexp flags from their coerced string values */
4093
  var reFlags = /\w*$/;
4094

    
4095
  /** Used to detected named functions */
4096
  var reFuncName = /^\s*function[ \n\r\t]+\w/;
4097

    
4098
  /** Used to match "interpolate" template delimiters */
4099
  var reInterpolate = /<%=([\s\S]+?)%>/g;
4100

    
4101
  /** Used to match leading whitespace and zeros to be removed */
4102
  var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
4103

    
4104
  /** Used to ensure capturing order of template delimiters */
4105
  var reNoMatch = /($^)/;
4106

    
4107
  /** Used to detect functions containing a `this` reference */
4108
  var reThis = /\bthis\b/;
4109

    
4110
  /** Used to match unescaped characters in compiled string literals */
4111
  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
4112

    
4113
  /** Used to assign default `context` object properties */
4114
  var contextProps = [
4115
    'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
4116
    'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
4117
    'parseInt', 'setTimeout'
4118
  ];
4119

    
4120
  /** Used to make template sourceURLs easier to identify */
4121
  var templateCounter = 0;
4122

    
4123
  /** `Object#toString` result shortcuts */
4124
  var argsClass = '[object Arguments]',
4125
      arrayClass = '[object Array]',
4126
      boolClass = '[object Boolean]',
4127
      dateClass = '[object Date]',
4128
      funcClass = '[object Function]',
4129
      numberClass = '[object Number]',
4130
      objectClass = '[object Object]',
4131
      regexpClass = '[object RegExp]',
4132
      stringClass = '[object String]';
4133

    
4134
  /** Used to identify object classifications that `_.clone` supports */
4135
  var cloneableClasses = {};
4136
  cloneableClasses[funcClass] = false;
4137
  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
4138
  cloneableClasses[boolClass] = cloneableClasses[dateClass] =
4139
  cloneableClasses[numberClass] = cloneableClasses[objectClass] =
4140
  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
4141

    
4142
  /** Used as an internal `_.debounce` options object */
4143
  var debounceOptions = {
4144
    'leading': false,
4145
    'maxWait': 0,
4146
    'trailing': false
4147
  };
4148

    
4149
  /** Used as the property descriptor for `__bindData__` */
4150
  var descriptor = {
4151
    'configurable': false,
4152
    'enumerable': false,
4153
    'value': null,
4154
    'writable': false
4155
  };
4156

    
4157
  /** Used to determine if values are of the language type Object */
4158
  var objectTypes = {
4159
    'boolean': false,
4160
    'function': true,
4161
    'object': true,
4162
    'number': false,
4163
    'string': false,
4164
    'undefined': false
4165
  };
4166

    
4167
  /** Used to escape characters for inclusion in compiled string literals */
4168
  var stringEscapes = {
4169
    '\\': '\\',
4170
    "'": "'",
4171
    '\n': 'n',
4172
    '\r': 'r',
4173
    '\t': 't',
4174
    '\u2028': 'u2028',
4175
    '\u2029': 'u2029'
4176
  };
4177

    
4178
  /** Used as a reference to the global object */
4179
  var root = (objectTypes[typeof window] && window) || this;
4180

    
4181
  /** Detect free variable `exports` */
4182
  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
4183

    
4184
  /** Detect free variable `module` */
4185
  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
4186

    
4187
  /** Detect the popular CommonJS extension `module.exports` */
4188
  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
4189

    
4190
  /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
4191
  var freeGlobal = objectTypes[typeof global] && global;
4192
  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
4193
    root = freeGlobal;
4194
  }
4195

    
4196
  /*--------------------------------------------------------------------------*/
4197

    
4198
  /**
4199
   * The base implementation of `_.indexOf` without support for binary searches
4200
   * or `fromIndex` constraints.
4201
   *
4202
   * @private
4203
   * @param {Array} array The array to search.
4204
   * @param {*} value The value to search for.
4205
   * @param {number} [fromIndex=0] The index to search from.
4206
   * @returns {number} Returns the index of the matched value or `-1`.
4207
   */
4208
  function baseIndexOf(array, value, fromIndex) {
4209
    var index = (fromIndex || 0) - 1,
4210
        length = array ? array.length : 0;
4211

    
4212
    while (++index < length) {
4213
      if (array[index] === value) {
4214
        return index;
4215
      }
4216
    }
4217
    return -1;
4218
  }
4219

    
4220
  /**
4221
   * An implementation of `_.contains` for cache objects that mimics the return
4222
   * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
4223
   *
4224
   * @private
4225
   * @param {Object} cache The cache object to inspect.
4226
   * @param {*} value The value to search for.
4227
   * @returns {number} Returns `0` if `value` is found, else `-1`.
4228
   */
4229
  function cacheIndexOf(cache, value) {
4230
    var type = typeof value;
4231
    cache = cache.cache;
4232

    
4233
    if (type == 'boolean' || value == null) {
4234
      return cache[value] ? 0 : -1;
4235
    }
4236
    if (type != 'number' && type != 'string') {
4237
      type = 'object';
4238
    }
4239
    var key = type == 'number' ? value : keyPrefix + value;
4240
    cache = (cache = cache[type]) && cache[key];
4241

    
4242
    return type == 'object'
4243
      ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
4244
      : (cache ? 0 : -1);
4245
  }
4246

    
4247
  /**
4248
   * Adds a given value to the corresponding cache object.
4249
   *
4250
   * @private
4251
   * @param {*} value The value to add to the cache.
4252
   */
4253
  function cachePush(value) {
4254
    var cache = this.cache,
4255
        type = typeof value;
4256

    
4257
    if (type == 'boolean' || value == null) {
4258
      cache[value] = true;
4259
    } else {
4260
      if (type != 'number' && type != 'string') {
4261
        type = 'object';
4262
      }
4263
      var key = type == 'number' ? value : keyPrefix + value,
4264
          typeCache = cache[type] || (cache[type] = {});
4265

    
4266
      if (type == 'object') {
4267
        (typeCache[key] || (typeCache[key] = [])).push(value);
4268
      } else {
4269
        typeCache[key] = true;
4270
      }
4271
    }
4272
  }
4273

    
4274
  /**
4275
   * Used by `_.max` and `_.min` as the default callback when a given
4276
   * collection is a string value.
4277
   *
4278
   * @private
4279
   * @param {string} value The character to inspect.
4280
   * @returns {number} Returns the code unit of given character.
4281
   */
4282
  function charAtCallback(value) {
4283
    return value.charCodeAt(0);
4284
  }
4285

    
4286
  /**
4287
   * Used by `sortBy` to compare transformed `collection` elements, stable sorting
4288
   * them in ascending order.
4289
   *
4290
   * @private
4291
   * @param {Object} a The object to compare to `b`.
4292
   * @param {Object} b The object to compare to `a`.
4293
   * @returns {number} Returns the sort order indicator of `1` or `-1`.
4294
   */
4295
  function compareAscending(a, b) {
4296
    var ac = a.criteria,
4297
        bc = b.criteria,
4298
        index = -1,
4299
        length = ac.length;
4300

    
4301
    while (++index < length) {
4302
      var value = ac[index],
4303
          other = bc[index];
4304

    
4305
      if (value !== other) {
4306
        if (value > other || typeof value == 'undefined') {
4307
          return 1;
4308
        }
4309
        if (value < other || typeof other == 'undefined') {
4310
          return -1;
4311
        }
4312
      }
4313
    }
4314
    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
4315
    // that causes it, under certain circumstances, to return the same value for
4316
    // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
4317
    //
4318
    // This also ensures a stable sort in V8 and other engines.
4319
    // See http://code.google.com/p/v8/issues/detail?id=90
4320
    return a.index - b.index;
4321
  }
4322

    
4323
  /**
4324
   * Creates a cache object to optimize linear searches of large arrays.
4325
   *
4326
   * @private
4327
   * @param {Array} [array=[]] The array to search.
4328
   * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
4329
   */
4330
  function createCache(array) {
4331
    var index = -1,
4332
        length = array.length,
4333
        first = array[0],
4334
        mid = array[(length / 2) | 0],
4335
        last = array[length - 1];
4336

    
4337
    if (first && typeof first == 'object' &&
4338
        mid && typeof mid == 'object' && last && typeof last == 'object') {
4339
      return false;
4340
    }
4341
    var cache = getObject();
4342
    cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
4343

    
4344
    var result = getObject();
4345
    result.array = array;
4346
    result.cache = cache;
4347
    result.push = cachePush;
4348

    
4349
    while (++index < length) {
4350
      result.push(array[index]);
4351
    }
4352
    return result;
4353
  }
4354

    
4355
  /**
4356
   * Used by `template` to escape characters for inclusion in compiled
4357
   * string literals.
4358
   *
4359
   * @private
4360
   * @param {string} match The matched character to escape.
4361
   * @returns {string} Returns the escaped character.
4362
   */
4363
  function escapeStringChar(match) {
4364
    return '\\' + stringEscapes[match];
4365
  }
4366

    
4367
  /**
4368
   * Gets an array from the array pool or creates a new one if the pool is empty.
4369
   *
4370
   * @private
4371
   * @returns {Array} The array from the pool.
4372
   */
4373
  function getArray() {
4374
    return arrayPool.pop() || [];
4375
  }
4376

    
4377
  /**
4378
   * Gets an object from the object pool or creates a new one if the pool is empty.
4379
   *
4380
   * @private
4381
   * @returns {Object} The object from the pool.
4382
   */
4383
  function getObject() {
4384
    return objectPool.pop() || {
4385
      'array': null,
4386
      'cache': null,
4387
      'criteria': null,
4388
      'false': false,
4389
      'index': 0,
4390
      'null': false,
4391
      'number': null,
4392
      'object': null,
4393
      'push': null,
4394
      'string': null,
4395
      'true': false,
4396
      'undefined': false,
4397
      'value': null
4398
    };
4399
  }
4400

    
4401
  /**
4402
   * Releases the given array back to the array pool.
4403
   *
4404
   * @private
4405
   * @param {Array} [array] The array to release.
4406
   */
4407
  function releaseArray(array) {
4408
    array.length = 0;
4409
    if (arrayPool.length < maxPoolSize) {
4410
      arrayPool.push(array);
4411
    }
4412
  }
4413

    
4414
  /**
4415
   * Releases the given object back to the object pool.
4416
   *
4417
   * @private
4418
   * @param {Object} [object] The object to release.
4419
   */
4420
  function releaseObject(object) {
4421
    var cache = object.cache;
4422
    if (cache) {
4423
      releaseObject(cache);
4424
    }
4425
    object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
4426
    if (objectPool.length < maxPoolSize) {
4427
      objectPool.push(object);
4428
    }
4429
  }
4430

    
4431
  /**
4432
   * Slices the `collection` from the `start` index up to, but not including,
4433
   * the `end` index.
4434
   *
4435
   * Note: This function is used instead of `Array#slice` to support node lists
4436
   * in IE < 9 and to ensure dense arrays are returned.
4437
   *
4438
   * @private
4439
   * @param {Array|Object|string} collection The collection to slice.
4440
   * @param {number} start The start index.
4441
   * @param {number} end The end index.
4442
   * @returns {Array} Returns the new array.
4443
   */
4444
  function slice(array, start, end) {
4445
    start || (start = 0);
4446
    if (typeof end == 'undefined') {
4447
      end = array ? array.length : 0;
4448
    }
4449
    var index = -1,
4450
        length = end - start || 0,
4451
        result = Array(length < 0 ? 0 : length);
4452

    
4453
    while (++index < length) {
4454
      result[index] = array[start + index];
4455
    }
4456
    return result;
4457
  }
4458

    
4459
  /*--------------------------------------------------------------------------*/
4460

    
4461
  /**
4462
   * Create a new `lodash` function using the given context object.
4463
   *
4464
   * @static
4465
   * @memberOf _
4466
   * @category Utilities
4467
   * @param {Object} [context=root] The context object.
4468
   * @returns {Function} Returns the `lodash` function.
4469
   */
4470
  function runInContext(context) {
4471
    // Avoid issues with some ES3 environments that attempt to use values, named
4472
    // after built-in constructors like `Object`, for the creation of literals.
4473
    // ES5 clears this up by stating that literals must use built-in constructors.
4474
    // See http://es5.github.io/#x11.1.5.
4475
    context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
4476

    
4477
    /** Native constructor references */
4478
    var Array = context.Array,
4479
        Boolean = context.Boolean,
4480
        Date = context.Date,
4481
        Function = context.Function,
4482
        Math = context.Math,
4483
        Number = context.Number,
4484
        Object = context.Object,
4485
        RegExp = context.RegExp,
4486
        String = context.String,
4487
        TypeError = context.TypeError;
4488

    
4489
    /**
4490
     * Used for `Array` method references.
4491
     *
4492
     * Normally `Array.prototype` would suffice, however, using an array literal
4493
     * avoids issues in Narwhal.
4494
     */
4495
    var arrayRef = [];
4496

    
4497
    /** Used for native method references */
4498
    var objectProto = Object.prototype;
4499

    
4500
    /** Used to restore the original `_` reference in `noConflict` */
4501
    var oldDash = context._;
4502

    
4503
    /** Used to resolve the internal [[Class]] of values */
4504
    var toString = objectProto.toString;
4505

    
4506
    /** Used to detect if a method is native */
4507
    var reNative = RegExp('^' +
4508
      String(toString)
4509
        .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
4510
        .replace(/toString| for [^\]]+/g, '.*?') + '$'
4511
    );
4512

    
4513
    /** Native method shortcuts */
4514
    var ceil = Math.ceil,
4515
        clearTimeout = context.clearTimeout,
4516
        floor = Math.floor,
4517
        fnToString = Function.prototype.toString,
4518
        getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
4519
        hasOwnProperty = objectProto.hasOwnProperty,
4520
        push = arrayRef.push,
4521
        setTimeout = context.setTimeout,
4522
        splice = arrayRef.splice,
4523
        unshift = arrayRef.unshift;
4524

    
4525
    /** Used to set meta data on functions */
4526
    var defineProperty = (function() {
4527
      // IE 8 only accepts DOM elements
4528
      try {
4529
        var o = {},
4530
            func = isNative(func = Object.defineProperty) && func,
4531
            result = func(o, o, o) && func;
4532
      } catch(e) { }
4533
      return result;
4534
    }());
4535

    
4536
    /* Native method shortcuts for methods with the same name as other `lodash` methods */
4537
    var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
4538
        nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
4539
        nativeIsFinite = context.isFinite,
4540
        nativeIsNaN = context.isNaN,
4541
        nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
4542
        nativeMax = Math.max,
4543
        nativeMin = Math.min,
4544
        nativeParseInt = context.parseInt,
4545
        nativeRandom = Math.random;
4546

    
4547
    /** Used to lookup a built-in constructor by [[Class]] */
4548
    var ctorByClass = {};
4549
    ctorByClass[arrayClass] = Array;
4550
    ctorByClass[boolClass] = Boolean;
4551
    ctorByClass[dateClass] = Date;
4552
    ctorByClass[funcClass] = Function;
4553
    ctorByClass[objectClass] = Object;
4554
    ctorByClass[numberClass] = Number;
4555
    ctorByClass[regexpClass] = RegExp;
4556
    ctorByClass[stringClass] = String;
4557

    
4558
    /*--------------------------------------------------------------------------*/
4559

    
4560
    /**
4561
     * Creates a `lodash` object which wraps the given value to enable intuitive
4562
     * method chaining.
4563
     *
4564
     * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
4565
     * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
4566
     * and `unshift`
4567
     *
4568
     * Chaining is supported in custom builds as long as the `value` method is
4569
     * implicitly or explicitly included in the build.
4570
     *
4571
     * The chainable wrapper functions are:
4572
     * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
4573
     * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
4574
     * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
4575
     * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
4576
     * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
4577
     * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
4578
     * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
4579
     * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
4580
     * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
4581
     * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
4582
     * and `zip`
4583
     *
4584
     * The non-chainable wrapper functions are:
4585
     * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
4586
     * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
4587
     * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
4588
     * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
4589
     * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
4590
     * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
4591
     * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
4592
     * `template`, `unescape`, `uniqueId`, and `value`
4593
     *
4594
     * The wrapper functions `first` and `last` return wrapped values when `n` is
4595
     * provided, otherwise they return unwrapped values.
4596
     *
4597
     * Explicit chaining can be enabled by using the `_.chain` method.
4598
     *
4599
     * @name _
4600
     * @constructor
4601
     * @category Chaining
4602
     * @param {*} value The value to wrap in a `lodash` instance.
4603
     * @returns {Object} Returns a `lodash` instance.
4604
     * @example
4605
     *
4606
     * var wrapped = _([1, 2, 3]);
4607
     *
4608
     * // returns an unwrapped value
4609
     * wrapped.reduce(function(sum, num) {
4610
     *   return sum + num;
4611
     * });
4612
     * // => 6
4613
     *
4614
     * // returns a wrapped value
4615
     * var squares = wrapped.map(function(num) {
4616
     *   return num * num;
4617
     * });
4618
     *
4619
     * _.isArray(squares);
4620
     * // => false
4621
     *
4622
     * _.isArray(squares.value());
4623
     * // => true
4624
     */
4625
    function lodash(value) {
4626
      // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
4627
      return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
4628
       ? value
4629
       : new lodashWrapper(value);
4630
    }
4631

    
4632
    /**
4633
     * A fast path for creating `lodash` wrapper objects.
4634
     *
4635
     * @private
4636
     * @param {*} value The value to wrap in a `lodash` instance.
4637
     * @param {boolean} chainAll A flag to enable chaining for all methods
4638
     * @returns {Object} Returns a `lodash` instance.
4639
     */
4640
    function lodashWrapper(value, chainAll) {
4641
      this.__chain__ = !!chainAll;
4642
      this.__wrapped__ = value;
4643
    }
4644
    // ensure `new lodashWrapper` is an instance of `lodash`
4645
    lodashWrapper.prototype = lodash.prototype;
4646

    
4647
    /**
4648
     * An object used to flag environments features.
4649
     *
4650
     * @static
4651
     * @memberOf _
4652
     * @type Object
4653
     */
4654
    var support = lodash.support = {};
4655

    
4656
    /**
4657
     * Detect if functions can be decompiled by `Function#toString`
4658
     * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
4659
     *
4660
     * @memberOf _.support
4661
     * @type boolean
4662
     */
4663
    support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
4664

    
4665
    /**
4666
     * Detect if `Function#name` is supported (all but IE).
4667
     *
4668
     * @memberOf _.support
4669
     * @type boolean
4670
     */
4671
    support.funcNames = typeof Function.name == 'string';
4672

    
4673
    /**
4674
     * By default, the template delimiters used by Lo-Dash are similar to those in
4675
     * embedded Ruby (ERB). Change the following template settings to use alternative
4676
     * delimiters.
4677
     *
4678
     * @static
4679
     * @memberOf _
4680
     * @type Object
4681
     */
4682
    lodash.templateSettings = {
4683

    
4684
      /**
4685
       * Used to detect `data` property values to be HTML-escaped.
4686
       *
4687
       * @memberOf _.templateSettings
4688
       * @type RegExp
4689
       */
4690
      'escape': /<%-([\s\S]+?)%>/g,
4691

    
4692
      /**
4693
       * Used to detect code to be evaluated.
4694
       *
4695
       * @memberOf _.templateSettings
4696
       * @type RegExp
4697
       */
4698
      'evaluate': /<%([\s\S]+?)%>/g,
4699

    
4700
      /**
4701
       * Used to detect `data` property values to inject.
4702
       *
4703
       * @memberOf _.templateSettings
4704
       * @type RegExp
4705
       */
4706
      'interpolate': reInterpolate,
4707

    
4708
      /**
4709
       * Used to reference the data object in the template text.
4710
       *
4711
       * @memberOf _.templateSettings
4712
       * @type string
4713
       */
4714
      'variable': '',
4715

    
4716
      /**
4717
       * Used to import variables into the compiled template.
4718
       *
4719
       * @memberOf _.templateSettings
4720
       * @type Object
4721
       */
4722
      'imports': {
4723

    
4724
        /**
4725
         * A reference to the `lodash` function.
4726
         *
4727
         * @memberOf _.templateSettings.imports
4728
         * @type Function
4729
         */
4730
        '_': lodash
4731
      }
4732
    };
4733

    
4734
    /*--------------------------------------------------------------------------*/
4735

    
4736
    /**
4737
     * The base implementation of `_.bind` that creates the bound function and
4738
     * sets its meta data.
4739
     *
4740
     * @private
4741
     * @param {Array} bindData The bind data array.
4742
     * @returns {Function} Returns the new bound function.
4743
     */
4744
    function baseBind(bindData) {
4745
      var func = bindData[0],
4746
          partialArgs = bindData[2],
4747
          thisArg = bindData[4];
4748

    
4749
      function bound() {
4750
        // `Function#bind` spec
4751
        // http://es5.github.io/#x15.3.4.5
4752
        if (partialArgs) {
4753
          // avoid `arguments` object deoptimizations by using `slice` instead
4754
          // of `Array.prototype.slice.call` and not assigning `arguments` to a
4755
          // variable as a ternary expression
4756
          var args = slice(partialArgs);
4757
          push.apply(args, arguments);
4758
        }
4759
        // mimic the constructor's `return` behavior
4760
        // http://es5.github.io/#x13.2.2
4761
        if (this instanceof bound) {
4762
          // ensure `new bound` is an instance of `func`
4763
          var thisBinding = baseCreate(func.prototype),
4764
              result = func.apply(thisBinding, args || arguments);
4765
          return isObject(result) ? result : thisBinding;
4766
        }
4767
        return func.apply(thisArg, args || arguments);
4768
      }
4769
      setBindData(bound, bindData);
4770
      return bound;
4771
    }
4772

    
4773
    /**
4774
     * The base implementation of `_.clone` without argument juggling or support
4775
     * for `thisArg` binding.
4776
     *
4777
     * @private
4778
     * @param {*} value The value to clone.
4779
     * @param {boolean} [isDeep=false] Specify a deep clone.
4780
     * @param {Function} [callback] The function to customize cloning values.
4781
     * @param {Array} [stackA=[]] Tracks traversed source objects.
4782
     * @param {Array} [stackB=[]] Associates clones with source counterparts.
4783
     * @returns {*} Returns the cloned value.
4784
     */
4785
    function baseClone(value, isDeep, callback, stackA, stackB) {
4786
      if (callback) {
4787
        var result = callback(value);
4788
        if (typeof result != 'undefined') {
4789
          return result;
4790
        }
4791
      }
4792
      // inspect [[Class]]
4793
      var isObj = isObject(value);
4794
      if (isObj) {
4795
        var className = toString.call(value);
4796
        if (!cloneableClasses[className]) {
4797
          return value;
4798
        }
4799
        var ctor = ctorByClass[className];
4800
        switch (className) {
4801
          case boolClass:
4802
          case dateClass:
4803
            return new ctor(+value);
4804

    
4805
          case numberClass:
4806
          case stringClass:
4807
            return new ctor(value);
4808

    
4809
          case regexpClass:
4810
            result = ctor(value.source, reFlags.exec(value));
4811
            result.lastIndex = value.lastIndex;
4812
            return result;
4813
        }
4814
      } else {
4815
        return value;
4816
      }
4817
      var isArr = isArray(value);
4818
      if (isDeep) {
4819
        // check for circular references and return corresponding clone
4820
        var initedStack = !stackA;
4821
        stackA || (stackA = getArray());
4822
        stackB || (stackB = getArray());
4823

    
4824
        var length = stackA.length;
4825
        while (length--) {
4826
          if (stackA[length] == value) {
4827
            return stackB[length];
4828
          }
4829
        }
4830
        result = isArr ? ctor(value.length) : {};
4831
      }
4832
      else {
4833
        result = isArr ? slice(value) : assign({}, value);
4834
      }
4835
      // add array properties assigned by `RegExp#exec`
4836
      if (isArr) {
4837
        if (hasOwnProperty.call(value, 'index')) {
4838
          result.index = value.index;
4839
        }
4840
        if (hasOwnProperty.call(value, 'input')) {
4841
          result.input = value.input;
4842
        }
4843
      }
4844
      // exit for shallow clone
4845
      if (!isDeep) {
4846
        return result;
4847
      }
4848
      // add the source value to the stack of traversed objects
4849
      // and associate it with its clone
4850
      stackA.push(value);
4851
      stackB.push(result);
4852

    
4853
      // recursively populate clone (susceptible to call stack limits)
4854
      (isArr ? forEach : forOwn)(value, function(objValue, key) {
4855
        result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
4856
      });
4857

    
4858
      if (initedStack) {
4859
        releaseArray(stackA);
4860
        releaseArray(stackB);
4861
      }
4862
      return result;
4863
    }
4864

    
4865
    /**
4866
     * The base implementation of `_.create` without support for assigning
4867
     * properties to the created object.
4868
     *
4869
     * @private
4870
     * @param {Object} prototype The object to inherit from.
4871
     * @returns {Object} Returns the new object.
4872
     */
4873
    function baseCreate(prototype, properties) {
4874
      return isObject(prototype) ? nativeCreate(prototype) : {};
4875
    }
4876
    // fallback for browsers without `Object.create`
4877
    if (!nativeCreate) {
4878
      baseCreate = (function() {
4879
        function Object() {}
4880
        return function(prototype) {
4881
          if (isObject(prototype)) {
4882
            Object.prototype = prototype;
4883
            var result = new Object;
4884
            Object.prototype = null;
4885
          }
4886
          return result || context.Object();
4887
        };
4888
      }());
4889
    }
4890

    
4891
    /**
4892
     * The base implementation of `_.createCallback` without support for creating
4893
     * "_.pluck" or "_.where" style callbacks.
4894
     *
4895
     * @private
4896
     * @param {*} [func=identity] The value to convert to a callback.
4897
     * @param {*} [thisArg] The `this` binding of the created callback.
4898
     * @param {number} [argCount] The number of arguments the callback accepts.
4899
     * @returns {Function} Returns a callback function.
4900
     */
4901
    function baseCreateCallback(func, thisArg, argCount) {
4902
      if (typeof func != 'function') {
4903
        return identity;
4904
      }
4905
      // exit early for no `thisArg` or already bound by `Function#bind`
4906
      if (typeof thisArg == 'undefined' || !('prototype' in func)) {
4907
        return func;
4908
      }
4909
      var bindData = func.__bindData__;
4910
      if (typeof bindData == 'undefined') {
4911
        if (support.funcNames) {
4912
          bindData = !func.name;
4913
        }
4914
        bindData = bindData || !support.funcDecomp;
4915
        if (!bindData) {
4916
          var source = fnToString.call(func);
4917
          if (!support.funcNames) {
4918
            bindData = !reFuncName.test(source);
4919
          }
4920
          if (!bindData) {
4921
            // checks if `func` references the `this` keyword and stores the result
4922
            bindData = reThis.test(source);
4923
            setBindData(func, bindData);
4924
          }
4925
        }
4926
      }
4927
      // exit early if there are no `this` references or `func` is bound
4928
      if (bindData === false || (bindData !== true && bindData[1] & 1)) {
4929
        return func;
4930
      }
4931
      switch (argCount) {
4932
        case 1: return function(value) {
4933
          return func.call(thisArg, value);
4934
        };
4935
        case 2: return function(a, b) {
4936
          return func.call(thisArg, a, b);
4937
        };
4938
        case 3: return function(value, index, collection) {
4939
          return func.call(thisArg, value, index, collection);
4940
        };
4941
        case 4: return function(accumulator, value, index, collection) {
4942
          return func.call(thisArg, accumulator, value, index, collection);
4943
        };
4944
      }
4945
      return bind(func, thisArg);
4946
    }
4947

    
4948
    /**
4949
     * The base implementation of `createWrapper` that creates the wrapper and
4950
     * sets its meta data.
4951
     *
4952
     * @private
4953
     * @param {Array} bindData The bind data array.
4954
     * @returns {Function} Returns the new function.
4955
     */
4956
    function baseCreateWrapper(bindData) {
4957
      var func = bindData[0],
4958
          bitmask = bindData[1],
4959
          partialArgs = bindData[2],
4960
          partialRightArgs = bindData[3],
4961
          thisArg = bindData[4],
4962
          arity = bindData[5];
4963

    
4964
      var isBind = bitmask & 1,
4965
          isBindKey = bitmask & 2,
4966
          isCurry = bitmask & 4,
4967
          isCurryBound = bitmask & 8,
4968
          key = func;
4969

    
4970
      function bound() {
4971
        var thisBinding = isBind ? thisArg : this;
4972
        if (partialArgs) {
4973
          var args = slice(partialArgs);
4974
          push.apply(args, arguments);
4975
        }
4976
        if (partialRightArgs || isCurry) {
4977
          args || (args = slice(arguments));
4978
          if (partialRightArgs) {
4979
            push.apply(args, partialRightArgs);
4980
          }
4981
          if (isCurry && args.length < arity) {
4982
            bitmask |= 16 & ~32;
4983
            return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
4984
          }
4985
        }
4986
        args || (args = arguments);
4987
        if (isBindKey) {
4988
          func = thisBinding[key];
4989
        }
4990
        if (this instanceof bound) {
4991
          thisBinding = baseCreate(func.prototype);
4992
          var result = func.apply(thisBinding, args);
4993
          return isObject(result) ? result : thisBinding;
4994
        }
4995
        return func.apply(thisBinding, args);
4996
      }
4997
      setBindData(bound, bindData);
4998
      return bound;
4999
    }
5000

    
5001
    /**
5002
     * The base implementation of `_.difference` that accepts a single array
5003
     * of values to exclude.
5004
     *
5005
     * @private
5006
     * @param {Array} array The array to process.
5007
     * @param {Array} [values] The array of values to exclude.
5008
     * @returns {Array} Returns a new array of filtered values.
5009
     */
5010
    function baseDifference(array, values) {
5011
      var index = -1,
5012
          indexOf = getIndexOf(),
5013
          length = array ? array.length : 0,
5014
          isLarge = length >= largeArraySize && indexOf === baseIndexOf,
5015
          result = [];
5016

    
5017
      if (isLarge) {
5018
        var cache = createCache(values);
5019
        if (cache) {
5020
          indexOf = cacheIndexOf;
5021
          values = cache;
5022
        } else {
5023
          isLarge = false;
5024
        }
5025
      }
5026
      while (++index < length) {
5027
        var value = array[index];
5028
        if (indexOf(values, value) < 0) {
5029
          result.push(value);
5030
        }
5031
      }
5032
      if (isLarge) {
5033
        releaseObject(values);
5034
      }
5035
      return result;
5036
    }
5037

    
5038
    /**
5039
     * The base implementation of `_.flatten` without support for callback
5040
     * shorthands or `thisArg` binding.
5041
     *
5042
     * @private
5043
     * @param {Array} array The array to flatten.
5044
     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
5045
     * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
5046
     * @param {number} [fromIndex=0] The index to start from.
5047
     * @returns {Array} Returns a new flattened array.
5048
     */
5049
    function baseFlatten(array, isShallow, isStrict, fromIndex) {
5050
      var index = (fromIndex || 0) - 1,
5051
          length = array ? array.length : 0,
5052
          result = [];
5053

    
5054
      while (++index < length) {
5055
        var value = array[index];
5056

    
5057
        if (value && typeof value == 'object' && typeof value.length == 'number'
5058
            && (isArray(value) || isArguments(value))) {
5059
          // recursively flatten arrays (susceptible to call stack limits)
5060
          if (!isShallow) {
5061
            value = baseFlatten(value, isShallow, isStrict);
5062
          }
5063
          var valIndex = -1,
5064
              valLength = value.length,
5065
              resIndex = result.length;
5066

    
5067
          result.length += valLength;
5068
          while (++valIndex < valLength) {
5069
            result[resIndex++] = value[valIndex];
5070
          }
5071
        } else if (!isStrict) {
5072
          result.push(value);
5073
        }
5074
      }
5075
      return result;
5076
    }
5077

    
5078
    /**
5079
     * The base implementation of `_.isEqual`, without support for `thisArg` binding,
5080
     * that allows partial "_.where" style comparisons.
5081
     *
5082
     * @private
5083
     * @param {*} a The value to compare.
5084
     * @param {*} b The other value to compare.
5085
     * @param {Function} [callback] The function to customize comparing values.
5086
     * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
5087
     * @param {Array} [stackA=[]] Tracks traversed `a` objects.
5088
     * @param {Array} [stackB=[]] Tracks traversed `b` objects.
5089
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
5090
     */
5091
    function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
5092
      // used to indicate that when comparing objects, `a` has at least the properties of `b`
5093
      if (callback) {
5094
        var result = callback(a, b);
5095
        if (typeof result != 'undefined') {
5096
          return !!result;
5097
        }
5098
      }
5099
      // exit early for identical values
5100
      if (a === b) {
5101
        // treat `+0` vs. `-0` as not equal
5102
        return a !== 0 || (1 / a == 1 / b);
5103
      }
5104
      var type = typeof a,
5105
          otherType = typeof b;
5106

    
5107
      // exit early for unlike primitive values
5108
      if (a === a &&
5109
          !(a && objectTypes[type]) &&
5110
          !(b && objectTypes[otherType])) {
5111
        return false;
5112
      }
5113
      // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
5114
      // http://es5.github.io/#x15.3.4.4
5115
      if (a == null || b == null) {
5116
        return a === b;
5117
      }
5118
      // compare [[Class]] names
5119
      var className = toString.call(a),
5120
          otherClass = toString.call(b);
5121

    
5122
      if (className == argsClass) {
5123
        className = objectClass;
5124
      }
5125
      if (otherClass == argsClass) {
5126
        otherClass = objectClass;
5127
      }
5128
      if (className != otherClass) {
5129
        return false;
5130
      }
5131
      switch (className) {
5132
        case boolClass:
5133
        case dateClass:
5134
          // coerce dates and booleans to numbers, dates to milliseconds and booleans
5135
          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
5136
          return +a == +b;
5137

    
5138
        case numberClass:
5139
          // treat `NaN` vs. `NaN` as equal
5140
          return (a != +a)
5141
            ? b != +b
5142
            // but treat `+0` vs. `-0` as not equal
5143
            : (a == 0 ? (1 / a == 1 / b) : a == +b);
5144

    
5145
        case regexpClass:
5146
        case stringClass:
5147
          // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
5148
          // treat string primitives and their corresponding object instances as equal
5149
          return a == String(b);
5150
      }
5151
      var isArr = className == arrayClass;
5152
      if (!isArr) {
5153
        // unwrap any `lodash` wrapped values
5154
        var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
5155
            bWrapped = hasOwnProperty.call(b, '__wrapped__');
5156

    
5157
        if (aWrapped || bWrapped) {
5158
          return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
5159
        }
5160
        // exit for functions and DOM nodes
5161
        if (className != objectClass) {
5162
          return false;
5163
        }
5164
        // in older versions of Opera, `arguments` objects have `Array` constructors
5165
        var ctorA = a.constructor,
5166
            ctorB = b.constructor;
5167

    
5168
        // non `Object` object instances with different constructors are not equal
5169
        if (ctorA != ctorB &&
5170
              !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
5171
              ('constructor' in a && 'constructor' in b)
5172
            ) {
5173
          return false;
5174
        }
5175
      }
5176
      // assume cyclic structures are equal
5177
      // the algorithm for detecting cyclic structures is adapted from ES 5.1
5178
      // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
5179
      var initedStack = !stackA;
5180
      stackA || (stackA = getArray());
5181
      stackB || (stackB = getArray());
5182

    
5183
      var length = stackA.length;
5184
      while (length--) {
5185
        if (stackA[length] == a) {
5186
          return stackB[length] == b;
5187
        }
5188
      }
5189
      var size = 0;
5190
      result = true;
5191

    
5192
      // add `a` and `b` to the stack of traversed objects
5193
      stackA.push(a);
5194
      stackB.push(b);
5195

    
5196
      // recursively compare objects and arrays (susceptible to call stack limits)
5197
      if (isArr) {
5198
        // compare lengths to determine if a deep comparison is necessary
5199
        length = a.length;
5200
        size = b.length;
5201
        result = size == length;
5202

    
5203
        if (result || isWhere) {
5204
          // deep compare the contents, ignoring non-numeric properties
5205
          while (size--) {
5206
            var index = length,
5207
                value = b[size];
5208

    
5209
            if (isWhere) {
5210
              while (index--) {
5211
                if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
5212
                  break;
5213
                }
5214
              }
5215
            } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
5216
              break;
5217
            }
5218
          }
5219
        }
5220
      }
5221
      else {
5222
        // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
5223
        // which, in this case, is more costly
5224
        forIn(b, function(value, key, b) {
5225
          if (hasOwnProperty.call(b, key)) {
5226
            // count the number of properties.
5227
            size++;
5228
            // deep compare each property value.
5229
            return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
5230
          }
5231
        });
5232

    
5233
        if (result && !isWhere) {
5234
          // ensure both objects have the same number of properties
5235
          forIn(a, function(value, key, a) {
5236
            if (hasOwnProperty.call(a, key)) {
5237
              // `size` will be `-1` if `a` has more properties than `b`
5238
              return (result = --size > -1);
5239
            }
5240
          });
5241
        }
5242
      }
5243
      stackA.pop();
5244
      stackB.pop();
5245

    
5246
      if (initedStack) {
5247
        releaseArray(stackA);
5248
        releaseArray(stackB);
5249
      }
5250
      return result;
5251
    }
5252

    
5253
    /**
5254
     * The base implementation of `_.merge` without argument juggling or support
5255
     * for `thisArg` binding.
5256
     *
5257
     * @private
5258
     * @param {Object} object The destination object.
5259
     * @param {Object} source The source object.
5260
     * @param {Function} [callback] The function to customize merging properties.
5261
     * @param {Array} [stackA=[]] Tracks traversed source objects.
5262
     * @param {Array} [stackB=[]] Associates values with source counterparts.
5263
     */
5264
    function baseMerge(object, source, callback, stackA, stackB) {
5265
      (isArray(source) ? forEach : forOwn)(source, function(source, key) {
5266
        var found,
5267
            isArr,
5268
            result = source,
5269
            value = object[key];
5270

    
5271
        if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
5272
          // avoid merging previously merged cyclic sources
5273
          var stackLength = stackA.length;
5274
          while (stackLength--) {
5275
            if ((found = stackA[stackLength] == source)) {
5276
              value = stackB[stackLength];
5277
              break;
5278
            }
5279
          }
5280
          if (!found) {
5281
            var isShallow;
5282
            if (callback) {
5283
              result = callback(value, source);
5284
              if ((isShallow = typeof result != 'undefined')) {
5285
                value = result;
5286
              }
5287
            }
5288
            if (!isShallow) {
5289
              value = isArr
5290
                ? (isArray(value) ? value : [])
5291
                : (isPlainObject(value) ? value : {});
5292
            }
5293
            // add `source` and associated `value` to the stack of traversed objects
5294
            stackA.push(source);
5295
            stackB.push(value);
5296

    
5297
            // recursively merge objects and arrays (susceptible to call stack limits)
5298
            if (!isShallow) {
5299
              baseMerge(value, source, callback, stackA, stackB);
5300
            }
5301
          }
5302
        }
5303
        else {
5304
          if (callback) {
5305
            result = callback(value, source);
5306
            if (typeof result == 'undefined') {
5307
              result = source;
5308
            }
5309
          }
5310
          if (typeof result != 'undefined') {
5311
            value = result;
5312
          }
5313
        }
5314
        object[key] = value;
5315
      });
5316
    }
5317

    
5318
    /**
5319
     * The base implementation of `_.random` without argument juggling or support
5320
     * for returning floating-point numbers.
5321
     *
5322
     * @private
5323
     * @param {number} min The minimum possible value.
5324
     * @param {number} max The maximum possible value.
5325
     * @returns {number} Returns a random number.
5326
     */
5327
    function baseRandom(min, max) {
5328
      return min + floor(nativeRandom() * (max - min + 1));
5329
    }
5330

    
5331
    /**
5332
     * The base implementation of `_.uniq` without support for callback shorthands
5333
     * or `thisArg` binding.
5334
     *
5335
     * @private
5336
     * @param {Array} array The array to process.
5337
     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
5338
     * @param {Function} [callback] The function called per iteration.
5339
     * @returns {Array} Returns a duplicate-value-free array.
5340
     */
5341
    function baseUniq(array, isSorted, callback) {
5342
      var index = -1,
5343
          indexOf = getIndexOf(),
5344
          length = array ? array.length : 0,
5345
          result = [];
5346

    
5347
      var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
5348
          seen = (callback || isLarge) ? getArray() : result;
5349

    
5350
      if (isLarge) {
5351
        var cache = createCache(seen);
5352
        indexOf = cacheIndexOf;
5353
        seen = cache;
5354
      }
5355
      while (++index < length) {
5356
        var value = array[index],
5357
            computed = callback ? callback(value, index, array) : value;
5358

    
5359
        if (isSorted
5360
              ? !index || seen[seen.length - 1] !== computed
5361
              : indexOf(seen, computed) < 0
5362
            ) {
5363
          if (callback || isLarge) {
5364
            seen.push(computed);
5365
          }
5366
          result.push(value);
5367
        }
5368
      }
5369
      if (isLarge) {
5370
        releaseArray(seen.array);
5371
        releaseObject(seen);
5372
      } else if (callback) {
5373
        releaseArray(seen);
5374
      }
5375
      return result;
5376
    }
5377

    
5378
    /**
5379
     * Creates a function that aggregates a collection, creating an object composed
5380
     * of keys generated from the results of running each element of the collection
5381
     * through a callback. The given `setter` function sets the keys and values
5382
     * of the composed object.
5383
     *
5384
     * @private
5385
     * @param {Function} setter The setter function.
5386
     * @returns {Function} Returns the new aggregator function.
5387
     */
5388
    function createAggregator(setter) {
5389
      return function(collection, callback, thisArg) {
5390
        var result = {};
5391
        callback = lodash.createCallback(callback, thisArg, 3);
5392

    
5393
        var index = -1,
5394
            length = collection ? collection.length : 0;
5395

    
5396
        if (typeof length == 'number') {
5397
          while (++index < length) {
5398
            var value = collection[index];
5399
            setter(result, value, callback(value, index, collection), collection);
5400
          }
5401
        } else {
5402
          forOwn(collection, function(value, key, collection) {
5403
            setter(result, value, callback(value, key, collection), collection);
5404
          });
5405
        }
5406
        return result;
5407
      };
5408
    }
5409

    
5410
    /**
5411
     * Creates a function that, when called, either curries or invokes `func`
5412
     * with an optional `this` binding and partially applied arguments.
5413
     *
5414
     * @private
5415
     * @param {Function|string} func The function or method name to reference.
5416
     * @param {number} bitmask The bitmask of method flags to compose.
5417
     *  The bitmask may be composed of the following flags:
5418
     *  1 - `_.bind`
5419
     *  2 - `_.bindKey`
5420
     *  4 - `_.curry`
5421
     *  8 - `_.curry` (bound)
5422
     *  16 - `_.partial`
5423
     *  32 - `_.partialRight`
5424
     * @param {Array} [partialArgs] An array of arguments to prepend to those
5425
     *  provided to the new function.
5426
     * @param {Array} [partialRightArgs] An array of arguments to append to those
5427
     *  provided to the new function.
5428
     * @param {*} [thisArg] The `this` binding of `func`.
5429
     * @param {number} [arity] The arity of `func`.
5430
     * @returns {Function} Returns the new function.
5431
     */
5432
    function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
5433
      var isBind = bitmask & 1,
5434
          isBindKey = bitmask & 2,
5435
          isCurry = bitmask & 4,
5436
          isCurryBound = bitmask & 8,
5437
          isPartial = bitmask & 16,
5438
          isPartialRight = bitmask & 32;
5439

    
5440
      if (!isBindKey && !isFunction(func)) {
5441
        throw new TypeError;
5442
      }
5443
      if (isPartial && !partialArgs.length) {
5444
        bitmask &= ~16;
5445
        isPartial = partialArgs = false;
5446
      }
5447
      if (isPartialRight && !partialRightArgs.length) {
5448
        bitmask &= ~32;
5449
        isPartialRight = partialRightArgs = false;
5450
      }
5451
      var bindData = func && func.__bindData__;
5452
      if (bindData && bindData !== true) {
5453
        // clone `bindData`
5454
        bindData = slice(bindData);
5455
        if (bindData[2]) {
5456
          bindData[2] = slice(bindData[2]);
5457
        }
5458
        if (bindData[3]) {
5459
          bindData[3] = slice(bindData[3]);
5460
        }
5461
        // set `thisBinding` is not previously bound
5462
        if (isBind && !(bindData[1] & 1)) {
5463
          bindData[4] = thisArg;
5464
        }
5465
        // set if previously bound but not currently (subsequent curried functions)
5466
        if (!isBind && bindData[1] & 1) {
5467
          bitmask |= 8;
5468
        }
5469
        // set curried arity if not yet set
5470
        if (isCurry && !(bindData[1] & 4)) {
5471
          bindData[5] = arity;
5472
        }
5473
        // append partial left arguments
5474
        if (isPartial) {
5475
          push.apply(bindData[2] || (bindData[2] = []), partialArgs);
5476
        }
5477
        // append partial right arguments
5478
        if (isPartialRight) {
5479
          unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
5480
        }
5481
        // merge flags
5482
        bindData[1] |= bitmask;
5483
        return createWrapper.apply(null, bindData);
5484
      }
5485
      // fast path for `_.bind`
5486
      var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
5487
      return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
5488
    }
5489

    
5490
    /**
5491
     * Used by `escape` to convert characters to HTML entities.
5492
     *
5493
     * @private
5494
     * @param {string} match The matched character to escape.
5495
     * @returns {string} Returns the escaped character.
5496
     */
5497
    function escapeHtmlChar(match) {
5498
      return htmlEscapes[match];
5499
    }
5500

    
5501
    /**
5502
     * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
5503
     * customized, this method returns the custom method, otherwise it returns
5504
     * the `baseIndexOf` function.
5505
     *
5506
     * @private
5507
     * @returns {Function} Returns the "indexOf" function.
5508
     */
5509
    function getIndexOf() {
5510
      var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
5511
      return result;
5512
    }
5513

    
5514
    /**
5515
     * Checks if `value` is a native function.
5516
     *
5517
     * @private
5518
     * @param {*} value The value to check.
5519
     * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
5520
     */
5521
    function isNative(value) {
5522
      return typeof value == 'function' && reNative.test(value);
5523
    }
5524

    
5525
    /**
5526
     * Sets `this` binding data on a given function.
5527
     *
5528
     * @private
5529
     * @param {Function} func The function to set data on.
5530
     * @param {Array} value The data array to set.
5531
     */
5532
    var setBindData = !defineProperty ? noop : function(func, value) {
5533
      descriptor.value = value;
5534
      defineProperty(func, '__bindData__', descriptor);
5535
    };
5536

    
5537
    /**
5538
     * A fallback implementation of `isPlainObject` which checks if a given value
5539
     * is an object created by the `Object` constructor, assuming objects created
5540
     * by the `Object` constructor have no inherited enumerable properties and that
5541
     * there are no `Object.prototype` extensions.
5542
     *
5543
     * @private
5544
     * @param {*} value The value to check.
5545
     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
5546
     */
5547
    function shimIsPlainObject(value) {
5548
      var ctor,
5549
          result;
5550

    
5551
      // avoid non Object objects, `arguments` objects, and DOM elements
5552
      if (!(value && toString.call(value) == objectClass) ||
5553
          (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
5554
        return false;
5555
      }
5556
      // In most environments an object's own properties are iterated before
5557
      // its inherited properties. If the last iterated property is an object's
5558
      // own property then there are no inherited enumerable properties.
5559
      forIn(value, function(value, key) {
5560
        result = key;
5561
      });
5562
      return typeof result == 'undefined' || hasOwnProperty.call(value, result);
5563
    }
5564

    
5565
    /**
5566
     * Used by `unescape` to convert HTML entities to characters.
5567
     *
5568
     * @private
5569
     * @param {string} match The matched character to unescape.
5570
     * @returns {string} Returns the unescaped character.
5571
     */
5572
    function unescapeHtmlChar(match) {
5573
      return htmlUnescapes[match];
5574
    }
5575

    
5576
    /*--------------------------------------------------------------------------*/
5577

    
5578
    /**
5579
     * Checks if `value` is an `arguments` object.
5580
     *
5581
     * @static
5582
     * @memberOf _
5583
     * @category Objects
5584
     * @param {*} value The value to check.
5585
     * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
5586
     * @example
5587
     *
5588
     * (function() { return _.isArguments(arguments); })(1, 2, 3);
5589
     * // => true
5590
     *
5591
     * _.isArguments([1, 2, 3]);
5592
     * // => false
5593
     */
5594
    function isArguments(value) {
5595
      return value && typeof value == 'object' && typeof value.length == 'number' &&
5596
        toString.call(value) == argsClass || false;
5597
    }
5598

    
5599
    /**
5600
     * Checks if `value` is an array.
5601
     *
5602
     * @static
5603
     * @memberOf _
5604
     * @type Function
5605
     * @category Objects
5606
     * @param {*} value The value to check.
5607
     * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
5608
     * @example
5609
     *
5610
     * (function() { return _.isArray(arguments); })();
5611
     * // => false
5612
     *
5613
     * _.isArray([1, 2, 3]);
5614
     * // => true
5615
     */
5616
    var isArray = nativeIsArray || function(value) {
5617
      return value && typeof value == 'object' && typeof value.length == 'number' &&
5618
        toString.call(value) == arrayClass || false;
5619
    };
5620

    
5621
    /**
5622
     * A fallback implementation of `Object.keys` which produces an array of the
5623
     * given object's own enumerable property names.
5624
     *
5625
     * @private
5626
     * @type Function
5627
     * @param {Object} object The object to inspect.
5628
     * @returns {Array} Returns an array of property names.
5629
     */
5630
    var shimKeys = function(object) {
5631
      var index, iterable = object, result = [];
5632
      if (!iterable) return result;
5633
      if (!(objectTypes[typeof object])) return result;
5634
        for (index in iterable) {
5635
          if (hasOwnProperty.call(iterable, index)) {
5636
            result.push(index);
5637
          }
5638
        }
5639
      return result
5640
    };
5641

    
5642
    /**
5643
     * Creates an array composed of the own enumerable property names of an object.
5644
     *
5645
     * @static
5646
     * @memberOf _
5647
     * @category Objects
5648
     * @param {Object} object The object to inspect.
5649
     * @returns {Array} Returns an array of property names.
5650
     * @example
5651
     *
5652
     * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
5653
     * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
5654
     */
5655
    var keys = !nativeKeys ? shimKeys : function(object) {
5656
      if (!isObject(object)) {
5657
        return [];
5658
      }
5659
      return nativeKeys(object);
5660
    };
5661

    
5662
    /**
5663
     * Used to convert characters to HTML entities:
5664
     *
5665
     * Though the `>` character is escaped for symmetry, characters like `>` and `/`
5666
     * don't require escaping in HTML and have no special meaning unless they're part
5667
     * of a tag or an unquoted attribute value.
5668
     * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
5669
     */
5670
    var htmlEscapes = {
5671
      '&': '&amp;',
5672
      '<': '&lt;',
5673
      '>': '&gt;',
5674
      '"': '&quot;',
5675
      "'": '&#39;'
5676
    };
5677

    
5678
    /** Used to convert HTML entities to characters */
5679
    var htmlUnescapes = invert(htmlEscapes);
5680

    
5681
    /** Used to match HTML entities and HTML characters */
5682
    var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
5683
        reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
5684

    
5685
    /*--------------------------------------------------------------------------*/
5686

    
5687
    /**
5688
     * Assigns own enumerable properties of source object(s) to the destination
5689
     * object. Subsequent sources will overwrite property assignments of previous
5690
     * sources. If a callback is provided it will be executed to produce the
5691
     * assigned values. The callback is bound to `thisArg` and invoked with two
5692
     * arguments; (objectValue, sourceValue).
5693
     *
5694
     * @static
5695
     * @memberOf _
5696
     * @type Function
5697
     * @alias extend
5698
     * @category Objects
5699
     * @param {Object} object The destination object.
5700
     * @param {...Object} [source] The source objects.
5701
     * @param {Function} [callback] The function to customize assigning values.
5702
     * @param {*} [thisArg] The `this` binding of `callback`.
5703
     * @returns {Object} Returns the destination object.
5704
     * @example
5705
     *
5706
     * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
5707
     * // => { 'name': 'fred', 'employer': 'slate' }
5708
     *
5709
     * var defaults = _.partialRight(_.assign, function(a, b) {
5710
     *   return typeof a == 'undefined' ? b : a;
5711
     * });
5712
     *
5713
     * var object = { 'name': 'barney' };
5714
     * defaults(object, { 'name': 'fred', 'employer': 'slate' });
5715
     * // => { 'name': 'barney', 'employer': 'slate' }
5716
     */
5717
    var assign = function(object, source, guard) {
5718
      var index, iterable = object, result = iterable;
5719
      if (!iterable) return result;
5720
      var args = arguments,
5721
          argsIndex = 0,
5722
          argsLength = typeof guard == 'number' ? 2 : args.length;
5723
      if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
5724
        var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
5725
      } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
5726
        callback = args[--argsLength];
5727
      }
5728
      while (++argsIndex < argsLength) {
5729
        iterable = args[argsIndex];
5730
        if (iterable && objectTypes[typeof iterable]) {
5731
        var ownIndex = -1,
5732
            ownProps = objectTypes[typeof iterable] && keys(iterable),
5733
            length = ownProps ? ownProps.length : 0;
5734

    
5735
        while (++ownIndex < length) {
5736
          index = ownProps[ownIndex];
5737
          result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
5738
        }
5739
        }
5740
      }
5741
      return result
5742
    };
5743

    
5744
    /**
5745
     * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
5746
     * be cloned, otherwise they will be assigned by reference. If a callback
5747
     * is provided it will be executed to produce the cloned values. If the
5748
     * callback returns `undefined` cloning will be handled by the method instead.
5749
     * The callback is bound to `thisArg` and invoked with one argument; (value).
5750
     *
5751
     * @static
5752
     * @memberOf _
5753
     * @category Objects
5754
     * @param {*} value The value to clone.
5755
     * @param {boolean} [isDeep=false] Specify a deep clone.
5756
     * @param {Function} [callback] The function to customize cloning values.
5757
     * @param {*} [thisArg] The `this` binding of `callback`.
5758
     * @returns {*} Returns the cloned value.
5759
     * @example
5760
     *
5761
     * var characters = [
5762
     *   { 'name': 'barney', 'age': 36 },
5763
     *   { 'name': 'fred',   'age': 40 }
5764
     * ];
5765
     *
5766
     * var shallow = _.clone(characters);
5767
     * shallow[0] === characters[0];
5768
     * // => true
5769
     *
5770
     * var deep = _.clone(characters, true);
5771
     * deep[0] === characters[0];
5772
     * // => false
5773
     *
5774
     * _.mixin({
5775
     *   'clone': _.partialRight(_.clone, function(value) {
5776
     *     return _.isElement(value) ? value.cloneNode(false) : undefined;
5777
     *   })
5778
     * });
5779
     *
5780
     * var clone = _.clone(document.body);
5781
     * clone.childNodes.length;
5782
     * // => 0
5783
     */
5784
    function clone(value, isDeep, callback, thisArg) {
5785
      // allows working with "Collections" methods without using their `index`
5786
      // and `collection` arguments for `isDeep` and `callback`
5787
      if (typeof isDeep != 'boolean' && isDeep != null) {
5788
        thisArg = callback;
5789
        callback = isDeep;
5790
        isDeep = false;
5791
      }
5792
      return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
5793
    }
5794

    
5795
    /**
5796
     * Creates a deep clone of `value`. If a callback is provided it will be
5797
     * executed to produce the cloned values. If the callback returns `undefined`
5798
     * cloning will be handled by the method instead. The callback is bound to
5799
     * `thisArg` and invoked with one argument; (value).
5800
     *
5801
     * Note: This method is loosely based on the structured clone algorithm. Functions
5802
     * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
5803
     * objects created by constructors other than `Object` are cloned to plain `Object` objects.
5804
     * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
5805
     *
5806
     * @static
5807
     * @memberOf _
5808
     * @category Objects
5809
     * @param {*} value The value to deep clone.
5810
     * @param {Function} [callback] The function to customize cloning values.
5811
     * @param {*} [thisArg] The `this` binding of `callback`.
5812
     * @returns {*} Returns the deep cloned value.
5813
     * @example
5814
     *
5815
     * var characters = [
5816
     *   { 'name': 'barney', 'age': 36 },
5817
     *   { 'name': 'fred',   'age': 40 }
5818
     * ];
5819
     *
5820
     * var deep = _.cloneDeep(characters);
5821
     * deep[0] === characters[0];
5822
     * // => false
5823
     *
5824
     * var view = {
5825
     *   'label': 'docs',
5826
     *   'node': element
5827
     * };
5828
     *
5829
     * var clone = _.cloneDeep(view, function(value) {
5830
     *   return _.isElement(value) ? value.cloneNode(true) : undefined;
5831
     * });
5832
     *
5833
     * clone.node == view.node;
5834
     * // => false
5835
     */
5836
    function cloneDeep(value, callback, thisArg) {
5837
      return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
5838
    }
5839

    
5840
    /**
5841
     * Creates an object that inherits from the given `prototype` object. If a
5842
     * `properties` object is provided its own enumerable properties are assigned
5843
     * to the created object.
5844
     *
5845
     * @static
5846
     * @memberOf _
5847
     * @category Objects
5848
     * @param {Object} prototype The object to inherit from.
5849
     * @param {Object} [properties] The properties to assign to the object.
5850
     * @returns {Object} Returns the new object.
5851
     * @example
5852
     *
5853
     * function Shape() {
5854
     *   this.x = 0;
5855
     *   this.y = 0;
5856
     * }
5857
     *
5858
     * function Circle() {
5859
     *   Shape.call(this);
5860
     * }
5861
     *
5862
     * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
5863
     *
5864
     * var circle = new Circle;
5865
     * circle instanceof Circle;
5866
     * // => true
5867
     *
5868
     * circle instanceof Shape;
5869
     * // => true
5870
     */
5871
    function create(prototype, properties) {
5872
      var result = baseCreate(prototype);
5873
      return properties ? assign(result, properties) : result;
5874
    }
5875

    
5876
    /**
5877
     * Assigns own enumerable properties of source object(s) to the destination
5878
     * object for all destination properties that resolve to `undefined`. Once a
5879
     * property is set, additional defaults of the same property will be ignored.
5880
     *
5881
     * @static
5882
     * @memberOf _
5883
     * @type Function
5884
     * @category Objects
5885
     * @param {Object} object The destination object.
5886
     * @param {...Object} [source] The source objects.
5887
     * @param- {Object} [guard] Allows working with `_.reduce` without using its
5888
     *  `key` and `object` arguments as sources.
5889
     * @returns {Object} Returns the destination object.
5890
     * @example
5891
     *
5892
     * var object = { 'name': 'barney' };
5893
     * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
5894
     * // => { 'name': 'barney', 'employer': 'slate' }
5895
     */
5896
    var defaults = function(object, source, guard) {
5897
      var index, iterable = object, result = iterable;
5898
      if (!iterable) return result;
5899
      var args = arguments,
5900
          argsIndex = 0,
5901
          argsLength = typeof guard == 'number' ? 2 : args.length;
5902
      while (++argsIndex < argsLength) {
5903
        iterable = args[argsIndex];
5904
        if (iterable && objectTypes[typeof iterable]) {
5905
        var ownIndex = -1,
5906
            ownProps = objectTypes[typeof iterable] && keys(iterable),
5907
            length = ownProps ? ownProps.length : 0;
5908

    
5909
        while (++ownIndex < length) {
5910
          index = ownProps[ownIndex];
5911
          if (typeof result[index] == 'undefined') result[index] = iterable[index];
5912
        }
5913
        }
5914
      }
5915
      return result
5916
    };
5917

    
5918
    /**
5919
     * This method is like `_.findIndex` except that it returns the key of the
5920
     * first element that passes the callback check, instead of the element itself.
5921
     *
5922
     * If a property name is provided for `callback` the created "_.pluck" style
5923
     * callback will return the property value of the given element.
5924
     *
5925
     * If an object is provided for `callback` the created "_.where" style callback
5926
     * will return `true` for elements that have the properties of the given object,
5927
     * else `false`.
5928
     *
5929
     * @static
5930
     * @memberOf _
5931
     * @category Objects
5932
     * @param {Object} object The object to search.
5933
     * @param {Function|Object|string} [callback=identity] The function called per
5934
     *  iteration. If a property name or object is provided it will be used to
5935
     *  create a "_.pluck" or "_.where" style callback, respectively.
5936
     * @param {*} [thisArg] The `this` binding of `callback`.
5937
     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
5938
     * @example
5939
     *
5940
     * var characters = {
5941
     *   'barney': {  'age': 36, 'blocked': false },
5942
     *   'fred': {    'age': 40, 'blocked': true },
5943
     *   'pebbles': { 'age': 1,  'blocked': false }
5944
     * };
5945
     *
5946
     * _.findKey(characters, function(chr) {
5947
     *   return chr.age < 40;
5948
     * });
5949
     * // => 'barney' (property order is not guaranteed across environments)
5950
     *
5951
     * // using "_.where" callback shorthand
5952
     * _.findKey(characters, { 'age': 1 });
5953
     * // => 'pebbles'
5954
     *
5955
     * // using "_.pluck" callback shorthand
5956
     * _.findKey(characters, 'blocked');
5957
     * // => 'fred'
5958
     */
5959
    function findKey(object, callback, thisArg) {
5960
      var result;
5961
      callback = lodash.createCallback(callback, thisArg, 3);
5962
      forOwn(object, function(value, key, object) {
5963
        if (callback(value, key, object)) {
5964
          result = key;
5965
          return false;
5966
        }
5967
      });
5968
      return result;
5969
    }
5970

    
5971
    /**
5972
     * This method is like `_.findKey` except that it iterates over elements
5973
     * of a `collection` in the opposite order.
5974
     *
5975
     * If a property name is provided for `callback` the created "_.pluck" style
5976
     * callback will return the property value of the given element.
5977
     *
5978
     * If an object is provided for `callback` the created "_.where" style callback
5979
     * will return `true` for elements that have the properties of the given object,
5980
     * else `false`.
5981
     *
5982
     * @static
5983
     * @memberOf _
5984
     * @category Objects
5985
     * @param {Object} object The object to search.
5986
     * @param {Function|Object|string} [callback=identity] The function called per
5987
     *  iteration. If a property name or object is provided it will be used to
5988
     *  create a "_.pluck" or "_.where" style callback, respectively.
5989
     * @param {*} [thisArg] The `this` binding of `callback`.
5990
     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
5991
     * @example
5992
     *
5993
     * var characters = {
5994
     *   'barney': {  'age': 36, 'blocked': true },
5995
     *   'fred': {    'age': 40, 'blocked': false },
5996
     *   'pebbles': { 'age': 1,  'blocked': true }
5997
     * };
5998
     *
5999
     * _.findLastKey(characters, function(chr) {
6000
     *   return chr.age < 40;
6001
     * });
6002
     * // => returns `pebbles`, assuming `_.findKey` returns `barney`
6003
     *
6004
     * // using "_.where" callback shorthand
6005
     * _.findLastKey(characters, { 'age': 40 });
6006
     * // => 'fred'
6007
     *
6008
     * // using "_.pluck" callback shorthand
6009
     * _.findLastKey(characters, 'blocked');
6010
     * // => 'pebbles'
6011
     */
6012
    function findLastKey(object, callback, thisArg) {
6013
      var result;
6014
      callback = lodash.createCallback(callback, thisArg, 3);
6015
      forOwnRight(object, function(value, key, object) {
6016
        if (callback(value, key, object)) {
6017
          result = key;
6018
          return false;
6019
        }
6020
      });
6021
      return result;
6022
    }
6023

    
6024
    /**
6025
     * Iterates over own and inherited enumerable properties of an object,
6026
     * executing the callback for each property. The callback is bound to `thisArg`
6027
     * and invoked with three arguments; (value, key, object). Callbacks may exit
6028
     * iteration early by explicitly returning `false`.
6029
     *
6030
     * @static
6031
     * @memberOf _
6032
     * @type Function
6033
     * @category Objects
6034
     * @param {Object} object The object to iterate over.
6035
     * @param {Function} [callback=identity] The function called per iteration.
6036
     * @param {*} [thisArg] The `this` binding of `callback`.
6037
     * @returns {Object} Returns `object`.
6038
     * @example
6039
     *
6040
     * function Shape() {
6041
     *   this.x = 0;
6042
     *   this.y = 0;
6043
     * }
6044
     *
6045
     * Shape.prototype.move = function(x, y) {
6046
     *   this.x += x;
6047
     *   this.y += y;
6048
     * };
6049
     *
6050
     * _.forIn(new Shape, function(value, key) {
6051
     *   console.log(key);
6052
     * });
6053
     * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
6054
     */
6055
    var forIn = function(collection, callback, thisArg) {
6056
      var index, iterable = collection, result = iterable;
6057
      if (!iterable) return result;
6058
      if (!objectTypes[typeof iterable]) return result;
6059
      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
6060
        for (index in iterable) {
6061
          if (callback(iterable[index], index, collection) === false) return result;
6062
        }
6063
      return result
6064
    };
6065

    
6066
    /**
6067
     * This method is like `_.forIn` except that it iterates over elements
6068
     * of a `collection` in the opposite order.
6069
     *
6070
     * @static
6071
     * @memberOf _
6072
     * @category Objects
6073
     * @param {Object} object The object to iterate over.
6074
     * @param {Function} [callback=identity] The function called per iteration.
6075
     * @param {*} [thisArg] The `this` binding of `callback`.
6076
     * @returns {Object} Returns `object`.
6077
     * @example
6078
     *
6079
     * function Shape() {
6080
     *   this.x = 0;
6081
     *   this.y = 0;
6082
     * }
6083
     *
6084
     * Shape.prototype.move = function(x, y) {
6085
     *   this.x += x;
6086
     *   this.y += y;
6087
     * };
6088
     *
6089
     * _.forInRight(new Shape, function(value, key) {
6090
     *   console.log(key);
6091
     * });
6092
     * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
6093
     */
6094
    function forInRight(object, callback, thisArg) {
6095
      var pairs = [];
6096

    
6097
      forIn(object, function(value, key) {
6098
        pairs.push(key, value);
6099
      });
6100

    
6101
      var length = pairs.length;
6102
      callback = baseCreateCallback(callback, thisArg, 3);
6103
      while (length--) {
6104
        if (callback(pairs[length--], pairs[length], object) === false) {
6105
          break;
6106
        }
6107
      }
6108
      return object;
6109
    }
6110

    
6111
    /**
6112
     * Iterates over own enumerable properties of an object, executing the callback
6113
     * for each property. The callback is bound to `thisArg` and invoked with three
6114
     * arguments; (value, key, object). Callbacks may exit iteration early by
6115
     * explicitly returning `false`.
6116
     *
6117
     * @static
6118
     * @memberOf _
6119
     * @type Function
6120
     * @category Objects
6121
     * @param {Object} object The object to iterate over.
6122
     * @param {Function} [callback=identity] The function called per iteration.
6123
     * @param {*} [thisArg] The `this` binding of `callback`.
6124
     * @returns {Object} Returns `object`.
6125
     * @example
6126
     *
6127
     * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
6128
     *   console.log(key);
6129
     * });
6130
     * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
6131
     */
6132
    var forOwn = function(collection, callback, thisArg) {
6133
      var index, iterable = collection, result = iterable;
6134
      if (!iterable) return result;
6135
      if (!objectTypes[typeof iterable]) return result;
6136
      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
6137
        var ownIndex = -1,
6138
            ownProps = objectTypes[typeof iterable] && keys(iterable),
6139
            length = ownProps ? ownProps.length : 0;
6140

    
6141
        while (++ownIndex < length) {
6142
          index = ownProps[ownIndex];
6143
          if (callback(iterable[index], index, collection) === false) return result;
6144
        }
6145
      return result
6146
    };
6147

    
6148
    /**
6149
     * This method is like `_.forOwn` except that it iterates over elements
6150
     * of a `collection` in the opposite order.
6151
     *
6152
     * @static
6153
     * @memberOf _
6154
     * @category Objects
6155
     * @param {Object} object The object to iterate over.
6156
     * @param {Function} [callback=identity] The function called per iteration.
6157
     * @param {*} [thisArg] The `this` binding of `callback`.
6158
     * @returns {Object} Returns `object`.
6159
     * @example
6160
     *
6161
     * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
6162
     *   console.log(key);
6163
     * });
6164
     * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
6165
     */
6166
    function forOwnRight(object, callback, thisArg) {
6167
      var props = keys(object),
6168
          length = props.length;
6169

    
6170
      callback = baseCreateCallback(callback, thisArg, 3);
6171
      while (length--) {
6172
        var key = props[length];
6173
        if (callback(object[key], key, object) === false) {
6174
          break;
6175
        }
6176
      }
6177
      return object;
6178
    }
6179

    
6180
    /**
6181
     * Creates a sorted array of property names of all enumerable properties,
6182
     * own and inherited, of `object` that have function values.
6183
     *
6184
     * @static
6185
     * @memberOf _
6186
     * @alias methods
6187
     * @category Objects
6188
     * @param {Object} object The object to inspect.
6189
     * @returns {Array} Returns an array of property names that have function values.
6190
     * @example
6191
     *
6192
     * _.functions(_);
6193
     * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
6194
     */
6195
    function functions(object) {
6196
      var result = [];
6197
      forIn(object, function(value, key) {
6198
        if (isFunction(value)) {
6199
          result.push(key);
6200
        }
6201
      });
6202
      return result.sort();
6203
    }
6204

    
6205
    /**
6206
     * Checks if the specified property name exists as a direct property of `object`,
6207
     * instead of an inherited property.
6208
     *
6209
     * @static
6210
     * @memberOf _
6211
     * @category Objects
6212
     * @param {Object} object The object to inspect.
6213
     * @param {string} key The name of the property to check.
6214
     * @returns {boolean} Returns `true` if key is a direct property, else `false`.
6215
     * @example
6216
     *
6217
     * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
6218
     * // => true
6219
     */
6220
    function has(object, key) {
6221
      return object ? hasOwnProperty.call(object, key) : false;
6222
    }
6223

    
6224
    /**
6225
     * Creates an object composed of the inverted keys and values of the given object.
6226
     *
6227
     * @static
6228
     * @memberOf _
6229
     * @category Objects
6230
     * @param {Object} object The object to invert.
6231
     * @returns {Object} Returns the created inverted object.
6232
     * @example
6233
     *
6234
     * _.invert({ 'first': 'fred', 'second': 'barney' });
6235
     * // => { 'fred': 'first', 'barney': 'second' }
6236
     */
6237
    function invert(object) {
6238
      var index = -1,
6239
          props = keys(object),
6240
          length = props.length,
6241
          result = {};
6242

    
6243
      while (++index < length) {
6244
        var key = props[index];
6245
        result[object[key]] = key;
6246
      }
6247
      return result;
6248
    }
6249

    
6250
    /**
6251
     * Checks if `value` is a boolean value.
6252
     *
6253
     * @static
6254
     * @memberOf _
6255
     * @category Objects
6256
     * @param {*} value The value to check.
6257
     * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
6258
     * @example
6259
     *
6260
     * _.isBoolean(null);
6261
     * // => false
6262
     */
6263
    function isBoolean(value) {
6264
      return value === true || value === false ||
6265
        value && typeof value == 'object' && toString.call(value) == boolClass || false;
6266
    }
6267

    
6268
    /**
6269
     * Checks if `value` is a date.
6270
     *
6271
     * @static
6272
     * @memberOf _
6273
     * @category Objects
6274
     * @param {*} value The value to check.
6275
     * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
6276
     * @example
6277
     *
6278
     * _.isDate(new Date);
6279
     * // => true
6280
     */
6281
    function isDate(value) {
6282
      return value && typeof value == 'object' && toString.call(value) == dateClass || false;
6283
    }
6284

    
6285
    /**
6286
     * Checks if `value` is a DOM element.
6287
     *
6288
     * @static
6289
     * @memberOf _
6290
     * @category Objects
6291
     * @param {*} value The value to check.
6292
     * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
6293
     * @example
6294
     *
6295
     * _.isElement(document.body);
6296
     * // => true
6297
     */
6298
    function isElement(value) {
6299
      return value && value.nodeType === 1 || false;
6300
    }
6301

    
6302
    /**
6303
     * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
6304
     * length of `0` and objects with no own enumerable properties are considered
6305
     * "empty".
6306
     *
6307
     * @static
6308
     * @memberOf _
6309
     * @category Objects
6310
     * @param {Array|Object|string} value The value to inspect.
6311
     * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
6312
     * @example
6313
     *
6314
     * _.isEmpty([1, 2, 3]);
6315
     * // => false
6316
     *
6317
     * _.isEmpty({});
6318
     * // => true
6319
     *
6320
     * _.isEmpty('');
6321
     * // => true
6322
     */
6323
    function isEmpty(value) {
6324
      var result = true;
6325
      if (!value) {
6326
        return result;
6327
      }
6328
      var className = toString.call(value),
6329
          length = value.length;
6330

    
6331
      if ((className == arrayClass || className == stringClass || className == argsClass ) ||
6332
          (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
6333
        return !length;
6334
      }
6335
      forOwn(value, function() {
6336
        return (result = false);
6337
      });
6338
      return result;
6339
    }
6340

    
6341
    /**
6342
     * Performs a deep comparison between two values to determine if they are
6343
     * equivalent to each other. If a callback is provided it will be executed
6344
     * to compare values. If the callback returns `undefined` comparisons will
6345
     * be handled by the method instead. The callback is bound to `thisArg` and
6346
     * invoked with two arguments; (a, b).
6347
     *
6348
     * @static
6349
     * @memberOf _
6350
     * @category Objects
6351
     * @param {*} a The value to compare.
6352
     * @param {*} b The other value to compare.
6353
     * @param {Function} [callback] The function to customize comparing values.
6354
     * @param {*} [thisArg] The `this` binding of `callback`.
6355
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
6356
     * @example
6357
     *
6358
     * var object = { 'name': 'fred' };
6359
     * var copy = { 'name': 'fred' };
6360
     *
6361
     * object == copy;
6362
     * // => false
6363
     *
6364
     * _.isEqual(object, copy);
6365
     * // => true
6366
     *
6367
     * var words = ['hello', 'goodbye'];
6368
     * var otherWords = ['hi', 'goodbye'];
6369
     *
6370
     * _.isEqual(words, otherWords, function(a, b) {
6371
     *   var reGreet = /^(?:hello|hi)$/i,
6372
     *       aGreet = _.isString(a) && reGreet.test(a),
6373
     *       bGreet = _.isString(b) && reGreet.test(b);
6374
     *
6375
     *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
6376
     * });
6377
     * // => true
6378
     */
6379
    function isEqual(a, b, callback, thisArg) {
6380
      return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
6381
    }
6382

    
6383
    /**
6384
     * Checks if `value` is, or can be coerced to, a finite number.
6385
     *
6386
     * Note: This is not the same as native `isFinite` which will return true for
6387
     * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
6388
     *
6389
     * @static
6390
     * @memberOf _
6391
     * @category Objects
6392
     * @param {*} value The value to check.
6393
     * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
6394
     * @example
6395
     *
6396
     * _.isFinite(-101);
6397
     * // => true
6398
     *
6399
     * _.isFinite('10');
6400
     * // => true
6401
     *
6402
     * _.isFinite(true);
6403
     * // => false
6404
     *
6405
     * _.isFinite('');
6406
     * // => false
6407
     *
6408
     * _.isFinite(Infinity);
6409
     * // => false
6410
     */
6411
    function isFinite(value) {
6412
      return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
6413
    }
6414

    
6415
    /**
6416
     * Checks if `value` is a function.
6417
     *
6418
     * @static
6419
     * @memberOf _
6420
     * @category Objects
6421
     * @param {*} value The value to check.
6422
     * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
6423
     * @example
6424
     *
6425
     * _.isFunction(_);
6426
     * // => true
6427
     */
6428
    function isFunction(value) {
6429
      return typeof value == 'function';
6430
    }
6431

    
6432
    /**
6433
     * Checks if `value` is the language type of Object.
6434
     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
6435
     *
6436
     * @static
6437
     * @memberOf _
6438
     * @category Objects
6439
     * @param {*} value The value to check.
6440
     * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
6441
     * @example
6442
     *
6443
     * _.isObject({});
6444
     * // => true
6445
     *
6446
     * _.isObject([1, 2, 3]);
6447
     * // => true
6448
     *
6449
     * _.isObject(1);
6450
     * // => false
6451
     */
6452
    function isObject(value) {
6453
      // check if the value is the ECMAScript language type of Object
6454
      // http://es5.github.io/#x8
6455
      // and avoid a V8 bug
6456
      // http://code.google.com/p/v8/issues/detail?id=2291
6457
      return !!(value && objectTypes[typeof value]);
6458
    }
6459

    
6460
    /**
6461
     * Checks if `value` is `NaN`.
6462
     *
6463
     * Note: This is not the same as native `isNaN` which will return `true` for
6464
     * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
6465
     *
6466
     * @static
6467
     * @memberOf _
6468
     * @category Objects
6469
     * @param {*} value The value to check.
6470
     * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
6471
     * @example
6472
     *
6473
     * _.isNaN(NaN);
6474
     * // => true
6475
     *
6476
     * _.isNaN(new Number(NaN));
6477
     * // => true
6478
     *
6479
     * isNaN(undefined);
6480
     * // => true
6481
     *
6482
     * _.isNaN(undefined);
6483
     * // => false
6484
     */
6485
    function isNaN(value) {
6486
      // `NaN` as a primitive is the only value that is not equal to itself
6487
      // (perform the [[Class]] check first to avoid errors with some host objects in IE)
6488
      return isNumber(value) && value != +value;
6489
    }
6490

    
6491
    /**
6492
     * Checks if `value` is `null`.
6493
     *
6494
     * @static
6495
     * @memberOf _
6496
     * @category Objects
6497
     * @param {*} value The value to check.
6498
     * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
6499
     * @example
6500
     *
6501
     * _.isNull(null);
6502
     * // => true
6503
     *
6504
     * _.isNull(undefined);
6505
     * // => false
6506
     */
6507
    function isNull(value) {
6508
      return value === null;
6509
    }
6510

    
6511
    /**
6512
     * Checks if `value` is a number.
6513
     *
6514
     * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
6515
     *
6516
     * @static
6517
     * @memberOf _
6518
     * @category Objects
6519
     * @param {*} value The value to check.
6520
     * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
6521
     * @example
6522
     *
6523
     * _.isNumber(8.4 * 5);
6524
     * // => true
6525
     */
6526
    function isNumber(value) {
6527
      return typeof value == 'number' ||
6528
        value && typeof value == 'object' && toString.call(value) == numberClass || false;
6529
    }
6530

    
6531
    /**
6532
     * Checks if `value` is an object created by the `Object` constructor.
6533
     *
6534
     * @static
6535
     * @memberOf _
6536
     * @category Objects
6537
     * @param {*} value The value to check.
6538
     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
6539
     * @example
6540
     *
6541
     * function Shape() {
6542
     *   this.x = 0;
6543
     *   this.y = 0;
6544
     * }
6545
     *
6546
     * _.isPlainObject(new Shape);
6547
     * // => false
6548
     *
6549
     * _.isPlainObject([1, 2, 3]);
6550
     * // => false
6551
     *
6552
     * _.isPlainObject({ 'x': 0, 'y': 0 });
6553
     * // => true
6554
     */
6555
    var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
6556
      if (!(value && toString.call(value) == objectClass)) {
6557
        return false;
6558
      }
6559
      var valueOf = value.valueOf,
6560
          objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
6561

    
6562
      return objProto
6563
        ? (value == objProto || getPrototypeOf(value) == objProto)
6564
        : shimIsPlainObject(value);
6565
    };
6566

    
6567
    /**
6568
     * Checks if `value` is a regular expression.
6569
     *
6570
     * @static
6571
     * @memberOf _
6572
     * @category Objects
6573
     * @param {*} value The value to check.
6574
     * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
6575
     * @example
6576
     *
6577
     * _.isRegExp(/fred/);
6578
     * // => true
6579
     */
6580
    function isRegExp(value) {
6581
      return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
6582
    }
6583

    
6584
    /**
6585
     * Checks if `value` is a string.
6586
     *
6587
     * @static
6588
     * @memberOf _
6589
     * @category Objects
6590
     * @param {*} value The value to check.
6591
     * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
6592
     * @example
6593
     *
6594
     * _.isString('fred');
6595
     * // => true
6596
     */
6597
    function isString(value) {
6598
      return typeof value == 'string' ||
6599
        value && typeof value == 'object' && toString.call(value) == stringClass || false;
6600
    }
6601

    
6602
    /**
6603
     * Checks if `value` is `undefined`.
6604
     *
6605
     * @static
6606
     * @memberOf _
6607
     * @category Objects
6608
     * @param {*} value The value to check.
6609
     * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
6610
     * @example
6611
     *
6612
     * _.isUndefined(void 0);
6613
     * // => true
6614
     */
6615
    function isUndefined(value) {
6616
      return typeof value == 'undefined';
6617
    }
6618

    
6619
    /**
6620
     * Creates an object with the same keys as `object` and values generated by
6621
     * running each own enumerable property of `object` through the callback.
6622
     * The callback is bound to `thisArg` and invoked with three arguments;
6623
     * (value, key, object).
6624
     *
6625
     * If a property name is provided for `callback` the created "_.pluck" style
6626
     * callback will return the property value of the given element.
6627
     *
6628
     * If an object is provided for `callback` the created "_.where" style callback
6629
     * will return `true` for elements that have the properties of the given object,
6630
     * else `false`.
6631
     *
6632
     * @static
6633
     * @memberOf _
6634
     * @category Objects
6635
     * @param {Object} object The object to iterate over.
6636
     * @param {Function|Object|string} [callback=identity] The function called
6637
     *  per iteration. If a property name or object is provided it will be used
6638
     *  to create a "_.pluck" or "_.where" style callback, respectively.
6639
     * @param {*} [thisArg] The `this` binding of `callback`.
6640
     * @returns {Array} Returns a new object with values of the results of each `callback` execution.
6641
     * @example
6642
     *
6643
     * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
6644
     * // => { 'a': 3, 'b': 6, 'c': 9 }
6645
     *
6646
     * var characters = {
6647
     *   'fred': { 'name': 'fred', 'age': 40 },
6648
     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
6649
     * };
6650
     *
6651
     * // using "_.pluck" callback shorthand
6652
     * _.mapValues(characters, 'age');
6653
     * // => { 'fred': 40, 'pebbles': 1 }
6654
     */
6655
    function mapValues(object, callback, thisArg) {
6656
      var result = {};
6657
      callback = lodash.createCallback(callback, thisArg, 3);
6658

    
6659
      forOwn(object, function(value, key, object) {
6660
        result[key] = callback(value, key, object);
6661
      });
6662
      return result;
6663
    }
6664

    
6665
    /**
6666
     * Recursively merges own enumerable properties of the source object(s), that
6667
     * don't resolve to `undefined` into the destination object. Subsequent sources
6668
     * will overwrite property assignments of previous sources. If a callback is
6669
     * provided it will be executed to produce the merged values of the destination
6670
     * and source properties. If the callback returns `undefined` merging will
6671
     * be handled by the method instead. The callback is bound to `thisArg` and
6672
     * invoked with two arguments; (objectValue, sourceValue).
6673
     *
6674
     * @static
6675
     * @memberOf _
6676
     * @category Objects
6677
     * @param {Object} object The destination object.
6678
     * @param {...Object} [source] The source objects.
6679
     * @param {Function} [callback] The function to customize merging properties.
6680
     * @param {*} [thisArg] The `this` binding of `callback`.
6681
     * @returns {Object} Returns the destination object.
6682
     * @example
6683
     *
6684
     * var names = {
6685
     *   'characters': [
6686
     *     { 'name': 'barney' },
6687
     *     { 'name': 'fred' }
6688
     *   ]
6689
     * };
6690
     *
6691
     * var ages = {
6692
     *   'characters': [
6693
     *     { 'age': 36 },
6694
     *     { 'age': 40 }
6695
     *   ]
6696
     * };
6697
     *
6698
     * _.merge(names, ages);
6699
     * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
6700
     *
6701
     * var food = {
6702
     *   'fruits': ['apple'],
6703
     *   'vegetables': ['beet']
6704
     * };
6705
     *
6706
     * var otherFood = {
6707
     *   'fruits': ['banana'],
6708
     *   'vegetables': ['carrot']
6709
     * };
6710
     *
6711
     * _.merge(food, otherFood, function(a, b) {
6712
     *   return _.isArray(a) ? a.concat(b) : undefined;
6713
     * });
6714
     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
6715
     */
6716
    function merge(object) {
6717
      var args = arguments,
6718
          length = 2;
6719

    
6720
      if (!isObject(object)) {
6721
        return object;
6722
      }
6723
      // allows working with `_.reduce` and `_.reduceRight` without using
6724
      // their `index` and `collection` arguments
6725
      if (typeof args[2] != 'number') {
6726
        length = args.length;
6727
      }
6728
      if (length > 3 && typeof args[length - 2] == 'function') {
6729
        var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
6730
      } else if (length > 2 && typeof args[length - 1] == 'function') {
6731
        callback = args[--length];
6732
      }
6733
      var sources = slice(arguments, 1, length),
6734
          index = -1,
6735
          stackA = getArray(),
6736
          stackB = getArray();
6737

    
6738
      while (++index < length) {
6739
        baseMerge(object, sources[index], callback, stackA, stackB);
6740
      }
6741
      releaseArray(stackA);
6742
      releaseArray(stackB);
6743
      return object;
6744
    }
6745

    
6746
    /**
6747
     * Creates a shallow clone of `object` excluding the specified properties.
6748
     * Property names may be specified as individual arguments or as arrays of
6749
     * property names. If a callback is provided it will be executed for each
6750
     * property of `object` omitting the properties the callback returns truey
6751
     * for. The callback is bound to `thisArg` and invoked with three arguments;
6752
     * (value, key, object).
6753
     *
6754
     * @static
6755
     * @memberOf _
6756
     * @category Objects
6757
     * @param {Object} object The source object.
6758
     * @param {Function|...string|string[]} [callback] The properties to omit or the
6759
     *  function called per iteration.
6760
     * @param {*} [thisArg] The `this` binding of `callback`.
6761
     * @returns {Object} Returns an object without the omitted properties.
6762
     * @example
6763
     *
6764
     * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
6765
     * // => { 'name': 'fred' }
6766
     *
6767
     * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
6768
     *   return typeof value == 'number';
6769
     * });
6770
     * // => { 'name': 'fred' }
6771
     */
6772
    function omit(object, callback, thisArg) {
6773
      var result = {};
6774
      if (typeof callback != 'function') {
6775
        var props = [];
6776
        forIn(object, function(value, key) {
6777
          props.push(key);
6778
        });
6779
        props = baseDifference(props, baseFlatten(arguments, true, false, 1));
6780

    
6781
        var index = -1,
6782
            length = props.length;
6783

    
6784
        while (++index < length) {
6785
          var key = props[index];
6786
          result[key] = object[key];
6787
        }
6788
      } else {
6789
        callback = lodash.createCallback(callback, thisArg, 3);
6790
        forIn(object, function(value, key, object) {
6791
          if (!callback(value, key, object)) {
6792
            result[key] = value;
6793
          }
6794
        });
6795
      }
6796
      return result;
6797
    }
6798

    
6799
    /**
6800
     * Creates a two dimensional array of an object's key-value pairs,
6801
     * i.e. `[[key1, value1], [key2, value2]]`.
6802
     *
6803
     * @static
6804
     * @memberOf _
6805
     * @category Objects
6806
     * @param {Object} object The object to inspect.
6807
     * @returns {Array} Returns new array of key-value pairs.
6808
     * @example
6809
     *
6810
     * _.pairs({ 'barney': 36, 'fred': 40 });
6811
     * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
6812
     */
6813
    function pairs(object) {
6814
      var index = -1,
6815
          props = keys(object),
6816
          length = props.length,
6817
          result = Array(length);
6818

    
6819
      while (++index < length) {
6820
        var key = props[index];
6821
        result[index] = [key, object[key]];
6822
      }
6823
      return result;
6824
    }
6825

    
6826
    /**
6827
     * Creates a shallow clone of `object` composed of the specified properties.
6828
     * Property names may be specified as individual arguments or as arrays of
6829
     * property names. If a callback is provided it will be executed for each
6830
     * property of `object` picking the properties the callback returns truey
6831
     * for. The callback is bound to `thisArg` and invoked with three arguments;
6832
     * (value, key, object).
6833
     *
6834
     * @static
6835
     * @memberOf _
6836
     * @category Objects
6837
     * @param {Object} object The source object.
6838
     * @param {Function|...string|string[]} [callback] The function called per
6839
     *  iteration or property names to pick, specified as individual property
6840
     *  names or arrays of property names.
6841
     * @param {*} [thisArg] The `this` binding of `callback`.
6842
     * @returns {Object} Returns an object composed of the picked properties.
6843
     * @example
6844
     *
6845
     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
6846
     * // => { 'name': 'fred' }
6847
     *
6848
     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
6849
     *   return key.charAt(0) != '_';
6850
     * });
6851
     * // => { 'name': 'fred' }
6852
     */
6853
    function pick(object, callback, thisArg) {
6854
      var result = {};
6855
      if (typeof callback != 'function') {
6856
        var index = -1,
6857
            props = baseFlatten(arguments, true, false, 1),
6858
            length = isObject(object) ? props.length : 0;
6859

    
6860
        while (++index < length) {
6861
          var key = props[index];
6862
          if (key in object) {
6863
            result[key] = object[key];
6864
          }
6865
        }
6866
      } else {
6867
        callback = lodash.createCallback(callback, thisArg, 3);
6868
        forIn(object, function(value, key, object) {
6869
          if (callback(value, key, object)) {
6870
            result[key] = value;
6871
          }
6872
        });
6873
      }
6874
      return result;
6875
    }
6876

    
6877
    /**
6878
     * An alternative to `_.reduce` this method transforms `object` to a new
6879
     * `accumulator` object which is the result of running each of its own
6880
     * enumerable properties through a callback, with each callback execution
6881
     * potentially mutating the `accumulator` object. The callback is bound to
6882
     * `thisArg` and invoked with four arguments; (accumulator, value, key, object).
6883
     * Callbacks may exit iteration early by explicitly returning `false`.
6884
     *
6885
     * @static
6886
     * @memberOf _
6887
     * @category Objects
6888
     * @param {Array|Object} object The object to iterate over.
6889
     * @param {Function} [callback=identity] The function called per iteration.
6890
     * @param {*} [accumulator] The custom accumulator value.
6891
     * @param {*} [thisArg] The `this` binding of `callback`.
6892
     * @returns {*} Returns the accumulated value.
6893
     * @example
6894
     *
6895
     * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
6896
     *   num *= num;
6897
     *   if (num % 2) {
6898
     *     return result.push(num) < 3;
6899
     *   }
6900
     * });
6901
     * // => [1, 9, 25]
6902
     *
6903
     * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
6904
     *   result[key] = num * 3;
6905
     * });
6906
     * // => { 'a': 3, 'b': 6, 'c': 9 }
6907
     */
6908
    function transform(object, callback, accumulator, thisArg) {
6909
      var isArr = isArray(object);
6910
      if (accumulator == null) {
6911
        if (isArr) {
6912
          accumulator = [];
6913
        } else {
6914
          var ctor = object && object.constructor,
6915
              proto = ctor && ctor.prototype;
6916

    
6917
          accumulator = baseCreate(proto);
6918
        }
6919
      }
6920
      if (callback) {
6921
        callback = lodash.createCallback(callback, thisArg, 4);
6922
        (isArr ? forEach : forOwn)(object, function(value, index, object) {
6923
          return callback(accumulator, value, index, object);
6924
        });
6925
      }
6926
      return accumulator;
6927
    }
6928

    
6929
    /**
6930
     * Creates an array composed of the own enumerable property values of `object`.
6931
     *
6932
     * @static
6933
     * @memberOf _
6934
     * @category Objects
6935
     * @param {Object} object The object to inspect.
6936
     * @returns {Array} Returns an array of property values.
6937
     * @example
6938
     *
6939
     * _.values({ 'one': 1, 'two': 2, 'three': 3 });
6940
     * // => [1, 2, 3] (property order is not guaranteed across environments)
6941
     */
6942
    function values(object) {
6943
      var index = -1,
6944
          props = keys(object),
6945
          length = props.length,
6946
          result = Array(length);
6947

    
6948
      while (++index < length) {
6949
        result[index] = object[props[index]];
6950
      }
6951
      return result;
6952
    }
6953

    
6954
    /*--------------------------------------------------------------------------*/
6955

    
6956
    /**
6957
     * Creates an array of elements from the specified indexes, or keys, of the
6958
     * `collection`. Indexes may be specified as individual arguments or as arrays
6959
     * of indexes.
6960
     *
6961
     * @static
6962
     * @memberOf _
6963
     * @category Collections
6964
     * @param {Array|Object|string} collection The collection to iterate over.
6965
     * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
6966
     *   to retrieve, specified as individual indexes or arrays of indexes.
6967
     * @returns {Array} Returns a new array of elements corresponding to the
6968
     *  provided indexes.
6969
     * @example
6970
     *
6971
     * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
6972
     * // => ['a', 'c', 'e']
6973
     *
6974
     * _.at(['fred', 'barney', 'pebbles'], 0, 2);
6975
     * // => ['fred', 'pebbles']
6976
     */
6977
    function at(collection) {
6978
      var args = arguments,
6979
          index = -1,
6980
          props = baseFlatten(args, true, false, 1),
6981
          length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
6982
          result = Array(length);
6983

    
6984
      while(++index < length) {
6985
        result[index] = collection[props[index]];
6986
      }
6987
      return result;
6988
    }
6989

    
6990
    /**
6991
     * Checks if a given value is present in a collection using strict equality
6992
     * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
6993
     * offset from the end of the collection.
6994
     *
6995
     * @static
6996
     * @memberOf _
6997
     * @alias include
6998
     * @category Collections
6999
     * @param {Array|Object|string} collection The collection to iterate over.
7000
     * @param {*} target The value to check for.
7001
     * @param {number} [fromIndex=0] The index to search from.
7002
     * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
7003
     * @example
7004
     *
7005
     * _.contains([1, 2, 3], 1);
7006
     * // => true
7007
     *
7008
     * _.contains([1, 2, 3], 1, 2);
7009
     * // => false
7010
     *
7011
     * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
7012
     * // => true
7013
     *
7014
     * _.contains('pebbles', 'eb');
7015
     * // => true
7016
     */
7017
    function contains(collection, target, fromIndex) {
7018
      var index = -1,
7019
          indexOf = getIndexOf(),
7020
          length = collection ? collection.length : 0,
7021
          result = false;
7022

    
7023
      fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
7024
      if (isArray(collection)) {
7025
        result = indexOf(collection, target, fromIndex) > -1;
7026
      } else if (typeof length == 'number') {
7027
        result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
7028
      } else {
7029
        forOwn(collection, function(value) {
7030
          if (++index >= fromIndex) {
7031
            return !(result = value === target);
7032
          }
7033
        });
7034
      }
7035
      return result;
7036
    }
7037

    
7038
    /**
7039
     * Creates an object composed of keys generated from the results of running
7040
     * each element of `collection` through the callback. The corresponding value
7041
     * of each key is the number of times the key was returned by the callback.
7042
     * The callback is bound to `thisArg` and invoked with three arguments;
7043
     * (value, index|key, collection).
7044
     *
7045
     * If a property name is provided for `callback` the created "_.pluck" style
7046
     * callback will return the property value of the given element.
7047
     *
7048
     * If an object is provided for `callback` the created "_.where" style callback
7049
     * will return `true` for elements that have the properties of the given object,
7050
     * else `false`.
7051
     *
7052
     * @static
7053
     * @memberOf _
7054
     * @category Collections
7055
     * @param {Array|Object|string} collection The collection to iterate over.
7056
     * @param {Function|Object|string} [callback=identity] The function called
7057
     *  per iteration. If a property name or object is provided it will be used
7058
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7059
     * @param {*} [thisArg] The `this` binding of `callback`.
7060
     * @returns {Object} Returns the composed aggregate object.
7061
     * @example
7062
     *
7063
     * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
7064
     * // => { '4': 1, '6': 2 }
7065
     *
7066
     * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
7067
     * // => { '4': 1, '6': 2 }
7068
     *
7069
     * _.countBy(['one', 'two', 'three'], 'length');
7070
     * // => { '3': 2, '5': 1 }
7071
     */
7072
    var countBy = createAggregator(function(result, value, key) {
7073
      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
7074
    });
7075

    
7076
    /**
7077
     * Checks if the given callback returns truey value for **all** elements of
7078
     * a collection. The callback is bound to `thisArg` and invoked with three
7079
     * arguments; (value, index|key, collection).
7080
     *
7081
     * If a property name is provided for `callback` the created "_.pluck" style
7082
     * callback will return the property value of the given element.
7083
     *
7084
     * If an object is provided for `callback` the created "_.where" style callback
7085
     * will return `true` for elements that have the properties of the given object,
7086
     * else `false`.
7087
     *
7088
     * @static
7089
     * @memberOf _
7090
     * @alias all
7091
     * @category Collections
7092
     * @param {Array|Object|string} collection The collection to iterate over.
7093
     * @param {Function|Object|string} [callback=identity] The function called
7094
     *  per iteration. If a property name or object is provided it will be used
7095
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7096
     * @param {*} [thisArg] The `this` binding of `callback`.
7097
     * @returns {boolean} Returns `true` if all elements passed the callback check,
7098
     *  else `false`.
7099
     * @example
7100
     *
7101
     * _.every([true, 1, null, 'yes']);
7102
     * // => false
7103
     *
7104
     * var characters = [
7105
     *   { 'name': 'barney', 'age': 36 },
7106
     *   { 'name': 'fred',   'age': 40 }
7107
     * ];
7108
     *
7109
     * // using "_.pluck" callback shorthand
7110
     * _.every(characters, 'age');
7111
     * // => true
7112
     *
7113
     * // using "_.where" callback shorthand
7114
     * _.every(characters, { 'age': 36 });
7115
     * // => false
7116
     */
7117
    function every(collection, callback, thisArg) {
7118
      var result = true;
7119
      callback = lodash.createCallback(callback, thisArg, 3);
7120

    
7121
      var index = -1,
7122
          length = collection ? collection.length : 0;
7123

    
7124
      if (typeof length == 'number') {
7125
        while (++index < length) {
7126
          if (!(result = !!callback(collection[index], index, collection))) {
7127
            break;
7128
          }
7129
        }
7130
      } else {
7131
        forOwn(collection, function(value, index, collection) {
7132
          return (result = !!callback(value, index, collection));
7133
        });
7134
      }
7135
      return result;
7136
    }
7137

    
7138
    /**
7139
     * Iterates over elements of a collection, returning an array of all elements
7140
     * the callback returns truey for. The callback is bound to `thisArg` and
7141
     * invoked with three arguments; (value, index|key, collection).
7142
     *
7143
     * If a property name is provided for `callback` the created "_.pluck" style
7144
     * callback will return the property value of the given element.
7145
     *
7146
     * If an object is provided for `callback` the created "_.where" style callback
7147
     * will return `true` for elements that have the properties of the given object,
7148
     * else `false`.
7149
     *
7150
     * @static
7151
     * @memberOf _
7152
     * @alias select
7153
     * @category Collections
7154
     * @param {Array|Object|string} collection The collection to iterate over.
7155
     * @param {Function|Object|string} [callback=identity] The function called
7156
     *  per iteration. If a property name or object is provided it will be used
7157
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7158
     * @param {*} [thisArg] The `this` binding of `callback`.
7159
     * @returns {Array} Returns a new array of elements that passed the callback check.
7160
     * @example
7161
     *
7162
     * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
7163
     * // => [2, 4, 6]
7164
     *
7165
     * var characters = [
7166
     *   { 'name': 'barney', 'age': 36, 'blocked': false },
7167
     *   { 'name': 'fred',   'age': 40, 'blocked': true }
7168
     * ];
7169
     *
7170
     * // using "_.pluck" callback shorthand
7171
     * _.filter(characters, 'blocked');
7172
     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
7173
     *
7174
     * // using "_.where" callback shorthand
7175
     * _.filter(characters, { 'age': 36 });
7176
     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
7177
     */
7178
    function filter(collection, callback, thisArg) {
7179
      var result = [];
7180
      callback = lodash.createCallback(callback, thisArg, 3);
7181

    
7182
      var index = -1,
7183
          length = collection ? collection.length : 0;
7184

    
7185
      if (typeof length == 'number') {
7186
        while (++index < length) {
7187
          var value = collection[index];
7188
          if (callback(value, index, collection)) {
7189
            result.push(value);
7190
          }
7191
        }
7192
      } else {
7193
        forOwn(collection, function(value, index, collection) {
7194
          if (callback(value, index, collection)) {
7195
            result.push(value);
7196
          }
7197
        });
7198
      }
7199
      return result;
7200
    }
7201

    
7202
    /**
7203
     * Iterates over elements of a collection, returning the first element that
7204
     * the callback returns truey for. The callback is bound to `thisArg` and
7205
     * invoked with three arguments; (value, index|key, collection).
7206
     *
7207
     * If a property name is provided for `callback` the created "_.pluck" style
7208
     * callback will return the property value of the given element.
7209
     *
7210
     * If an object is provided for `callback` the created "_.where" style callback
7211
     * will return `true` for elements that have the properties of the given object,
7212
     * else `false`.
7213
     *
7214
     * @static
7215
     * @memberOf _
7216
     * @alias detect, findWhere
7217
     * @category Collections
7218
     * @param {Array|Object|string} collection The collection to iterate over.
7219
     * @param {Function|Object|string} [callback=identity] The function called
7220
     *  per iteration. If a property name or object is provided it will be used
7221
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7222
     * @param {*} [thisArg] The `this` binding of `callback`.
7223
     * @returns {*} Returns the found element, else `undefined`.
7224
     * @example
7225
     *
7226
     * var characters = [
7227
     *   { 'name': 'barney',  'age': 36, 'blocked': false },
7228
     *   { 'name': 'fred',    'age': 40, 'blocked': true },
7229
     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
7230
     * ];
7231
     *
7232
     * _.find(characters, function(chr) {
7233
     *   return chr.age < 40;
7234
     * });
7235
     * // => { 'name': 'barney', 'age': 36, 'blocked': false }
7236
     *
7237
     * // using "_.where" callback shorthand
7238
     * _.find(characters, { 'age': 1 });
7239
     * // =>  { 'name': 'pebbles', 'age': 1, 'blocked': false }
7240
     *
7241
     * // using "_.pluck" callback shorthand
7242
     * _.find(characters, 'blocked');
7243
     * // => { 'name': 'fred', 'age': 40, 'blocked': true }
7244
     */
7245
    function find(collection, callback, thisArg) {
7246
      callback = lodash.createCallback(callback, thisArg, 3);
7247

    
7248
      var index = -1,
7249
          length = collection ? collection.length : 0;
7250

    
7251
      if (typeof length == 'number') {
7252
        while (++index < length) {
7253
          var value = collection[index];
7254
          if (callback(value, index, collection)) {
7255
            return value;
7256
          }
7257
        }
7258
      } else {
7259
        var result;
7260
        forOwn(collection, function(value, index, collection) {
7261
          if (callback(value, index, collection)) {
7262
            result = value;
7263
            return false;
7264
          }
7265
        });
7266
        return result;
7267
      }
7268
    }
7269

    
7270
    /**
7271
     * This method is like `_.find` except that it iterates over elements
7272
     * of a `collection` from right to left.
7273
     *
7274
     * @static
7275
     * @memberOf _
7276
     * @category Collections
7277
     * @param {Array|Object|string} collection The collection to iterate over.
7278
     * @param {Function|Object|string} [callback=identity] The function called
7279
     *  per iteration. If a property name or object is provided it will be used
7280
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7281
     * @param {*} [thisArg] The `this` binding of `callback`.
7282
     * @returns {*} Returns the found element, else `undefined`.
7283
     * @example
7284
     *
7285
     * _.findLast([1, 2, 3, 4], function(num) {
7286
     *   return num % 2 == 1;
7287
     * });
7288
     * // => 3
7289
     */
7290
    function findLast(collection, callback, thisArg) {
7291
      var result;
7292
      callback = lodash.createCallback(callback, thisArg, 3);
7293
      forEachRight(collection, function(value, index, collection) {
7294
        if (callback(value, index, collection)) {
7295
          result = value;
7296
          return false;
7297
        }
7298
      });
7299
      return result;
7300
    }
7301

    
7302
    /**
7303
     * Iterates over elements of a collection, executing the callback for each
7304
     * element. The callback is bound to `thisArg` and invoked with three arguments;
7305
     * (value, index|key, collection). Callbacks may exit iteration early by
7306
     * explicitly returning `false`.
7307
     *
7308
     * Note: As with other "Collections" methods, objects with a `length` property
7309
     * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
7310
     * may be used for object iteration.
7311
     *
7312
     * @static
7313
     * @memberOf _
7314
     * @alias each
7315
     * @category Collections
7316
     * @param {Array|Object|string} collection The collection to iterate over.
7317
     * @param {Function} [callback=identity] The function called per iteration.
7318
     * @param {*} [thisArg] The `this` binding of `callback`.
7319
     * @returns {Array|Object|string} Returns `collection`.
7320
     * @example
7321
     *
7322
     * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
7323
     * // => logs each number and returns '1,2,3'
7324
     *
7325
     * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
7326
     * // => logs each number and returns the object (property order is not guaranteed across environments)
7327
     */
7328
    function forEach(collection, callback, thisArg) {
7329
      var index = -1,
7330
          length = collection ? collection.length : 0;
7331

    
7332
      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
7333
      if (typeof length == 'number') {
7334
        while (++index < length) {
7335
          if (callback(collection[index], index, collection) === false) {
7336
            break;
7337
          }
7338
        }
7339
      } else {
7340
        forOwn(collection, callback);
7341
      }
7342
      return collection;
7343
    }
7344

    
7345
    /**
7346
     * This method is like `_.forEach` except that it iterates over elements
7347
     * of a `collection` from right to left.
7348
     *
7349
     * @static
7350
     * @memberOf _
7351
     * @alias eachRight
7352
     * @category Collections
7353
     * @param {Array|Object|string} collection The collection to iterate over.
7354
     * @param {Function} [callback=identity] The function called per iteration.
7355
     * @param {*} [thisArg] The `this` binding of `callback`.
7356
     * @returns {Array|Object|string} Returns `collection`.
7357
     * @example
7358
     *
7359
     * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
7360
     * // => logs each number from right to left and returns '3,2,1'
7361
     */
7362
    function forEachRight(collection, callback, thisArg) {
7363
      var length = collection ? collection.length : 0;
7364
      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
7365
      if (typeof length == 'number') {
7366
        while (length--) {
7367
          if (callback(collection[length], length, collection) === false) {
7368
            break;
7369
          }
7370
        }
7371
      } else {
7372
        var props = keys(collection);
7373
        length = props.length;
7374
        forOwn(collection, function(value, key, collection) {
7375
          key = props ? props[--length] : --length;
7376
          return callback(collection[key], key, collection);
7377
        });
7378
      }
7379
      return collection;
7380
    }
7381

    
7382
    /**
7383
     * Creates an object composed of keys generated from the results of running
7384
     * each element of a collection through the callback. The corresponding value
7385
     * of each key is an array of the elements responsible for generating the key.
7386
     * The callback is bound to `thisArg` and invoked with three arguments;
7387
     * (value, index|key, collection).
7388
     *
7389
     * If a property name is provided for `callback` the created "_.pluck" style
7390
     * callback will return the property value of the given element.
7391
     *
7392
     * If an object is provided for `callback` the created "_.where" style callback
7393
     * will return `true` for elements that have the properties of the given object,
7394
     * else `false`
7395
     *
7396
     * @static
7397
     * @memberOf _
7398
     * @category Collections
7399
     * @param {Array|Object|string} collection The collection to iterate over.
7400
     * @param {Function|Object|string} [callback=identity] The function called
7401
     *  per iteration. If a property name or object is provided it will be used
7402
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7403
     * @param {*} [thisArg] The `this` binding of `callback`.
7404
     * @returns {Object} Returns the composed aggregate object.
7405
     * @example
7406
     *
7407
     * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
7408
     * // => { '4': [4.2], '6': [6.1, 6.4] }
7409
     *
7410
     * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
7411
     * // => { '4': [4.2], '6': [6.1, 6.4] }
7412
     *
7413
     * // using "_.pluck" callback shorthand
7414
     * _.groupBy(['one', 'two', 'three'], 'length');
7415
     * // => { '3': ['one', 'two'], '5': ['three'] }
7416
     */
7417
    var groupBy = createAggregator(function(result, value, key) {
7418
      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
7419
    });
7420

    
7421
    /**
7422
     * Creates an object composed of keys generated from the results of running
7423
     * each element of the collection through the given callback. The corresponding
7424
     * value of each key is the last element responsible for generating the key.
7425
     * The callback is bound to `thisArg` and invoked with three arguments;
7426
     * (value, index|key, collection).
7427
     *
7428
     * If a property name is provided for `callback` the created "_.pluck" style
7429
     * callback will return the property value of the given element.
7430
     *
7431
     * If an object is provided for `callback` the created "_.where" style callback
7432
     * will return `true` for elements that have the properties of the given object,
7433
     * else `false`.
7434
     *
7435
     * @static
7436
     * @memberOf _
7437
     * @category Collections
7438
     * @param {Array|Object|string} collection The collection to iterate over.
7439
     * @param {Function|Object|string} [callback=identity] The function called
7440
     *  per iteration. If a property name or object is provided it will be used
7441
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7442
     * @param {*} [thisArg] The `this` binding of `callback`.
7443
     * @returns {Object} Returns the composed aggregate object.
7444
     * @example
7445
     *
7446
     * var keys = [
7447
     *   { 'dir': 'left', 'code': 97 },
7448
     *   { 'dir': 'right', 'code': 100 }
7449
     * ];
7450
     *
7451
     * _.indexBy(keys, 'dir');
7452
     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
7453
     *
7454
     * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
7455
     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
7456
     *
7457
     * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
7458
     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
7459
     */
7460
    var indexBy = createAggregator(function(result, value, key) {
7461
      result[key] = value;
7462
    });
7463

    
7464
    /**
7465
     * Invokes the method named by `methodName` on each element in the `collection`
7466
     * returning an array of the results of each invoked method. Additional arguments
7467
     * will be provided to each invoked method. If `methodName` is a function it
7468
     * will be invoked for, and `this` bound to, each element in the `collection`.
7469
     *
7470
     * @static
7471
     * @memberOf _
7472
     * @category Collections
7473
     * @param {Array|Object|string} collection The collection to iterate over.
7474
     * @param {Function|string} methodName The name of the method to invoke or
7475
     *  the function invoked per iteration.
7476
     * @param {...*} [arg] Arguments to invoke the method with.
7477
     * @returns {Array} Returns a new array of the results of each invoked method.
7478
     * @example
7479
     *
7480
     * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
7481
     * // => [[1, 5, 7], [1, 2, 3]]
7482
     *
7483
     * _.invoke([123, 456], String.prototype.split, '');
7484
     * // => [['1', '2', '3'], ['4', '5', '6']]
7485
     */
7486
    function invoke(collection, methodName) {
7487
      var args = slice(arguments, 2),
7488
          index = -1,
7489
          isFunc = typeof methodName == 'function',
7490
          length = collection ? collection.length : 0,
7491
          result = Array(typeof length == 'number' ? length : 0);
7492

    
7493
      forEach(collection, function(value) {
7494
        result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
7495
      });
7496
      return result;
7497
    }
7498

    
7499
    /**
7500
     * Creates an array of values by running each element in the collection
7501
     * through the callback. The callback is bound to `thisArg` and invoked with
7502
     * three arguments; (value, index|key, collection).
7503
     *
7504
     * If a property name is provided for `callback` the created "_.pluck" style
7505
     * callback will return the property value of the given element.
7506
     *
7507
     * If an object is provided for `callback` the created "_.where" style callback
7508
     * will return `true` for elements that have the properties of the given object,
7509
     * else `false`.
7510
     *
7511
     * @static
7512
     * @memberOf _
7513
     * @alias collect
7514
     * @category Collections
7515
     * @param {Array|Object|string} collection The collection to iterate over.
7516
     * @param {Function|Object|string} [callback=identity] The function called
7517
     *  per iteration. If a property name or object is provided it will be used
7518
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7519
     * @param {*} [thisArg] The `this` binding of `callback`.
7520
     * @returns {Array} Returns a new array of the results of each `callback` execution.
7521
     * @example
7522
     *
7523
     * _.map([1, 2, 3], function(num) { return num * 3; });
7524
     * // => [3, 6, 9]
7525
     *
7526
     * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
7527
     * // => [3, 6, 9] (property order is not guaranteed across environments)
7528
     *
7529
     * var characters = [
7530
     *   { 'name': 'barney', 'age': 36 },
7531
     *   { 'name': 'fred',   'age': 40 }
7532
     * ];
7533
     *
7534
     * // using "_.pluck" callback shorthand
7535
     * _.map(characters, 'name');
7536
     * // => ['barney', 'fred']
7537
     */
7538
    function map(collection, callback, thisArg) {
7539
      var index = -1,
7540
          length = collection ? collection.length : 0;
7541

    
7542
      callback = lodash.createCallback(callback, thisArg, 3);
7543
      if (typeof length == 'number') {
7544
        var result = Array(length);
7545
        while (++index < length) {
7546
          result[index] = callback(collection[index], index, collection);
7547
        }
7548
      } else {
7549
        result = [];
7550
        forOwn(collection, function(value, key, collection) {
7551
          result[++index] = callback(value, key, collection);
7552
        });
7553
      }
7554
      return result;
7555
    }
7556

    
7557
    /**
7558
     * Retrieves the maximum value of a collection. If the collection is empty or
7559
     * falsey `-Infinity` is returned. If a callback is provided it will be executed
7560
     * for each value in the collection to generate the criterion by which the value
7561
     * is ranked. The callback is bound to `thisArg` and invoked with three
7562
     * arguments; (value, index, collection).
7563
     *
7564
     * If a property name is provided for `callback` the created "_.pluck" style
7565
     * callback will return the property value of the given element.
7566
     *
7567
     * If an object is provided for `callback` the created "_.where" style callback
7568
     * will return `true` for elements that have the properties of the given object,
7569
     * else `false`.
7570
     *
7571
     * @static
7572
     * @memberOf _
7573
     * @category Collections
7574
     * @param {Array|Object|string} collection The collection to iterate over.
7575
     * @param {Function|Object|string} [callback=identity] The function called
7576
     *  per iteration. If a property name or object is provided it will be used
7577
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7578
     * @param {*} [thisArg] The `this` binding of `callback`.
7579
     * @returns {*} Returns the maximum value.
7580
     * @example
7581
     *
7582
     * _.max([4, 2, 8, 6]);
7583
     * // => 8
7584
     *
7585
     * var characters = [
7586
     *   { 'name': 'barney', 'age': 36 },
7587
     *   { 'name': 'fred',   'age': 40 }
7588
     * ];
7589
     *
7590
     * _.max(characters, function(chr) { return chr.age; });
7591
     * // => { 'name': 'fred', 'age': 40 };
7592
     *
7593
     * // using "_.pluck" callback shorthand
7594
     * _.max(characters, 'age');
7595
     * // => { 'name': 'fred', 'age': 40 };
7596
     */
7597
    function max(collection, callback, thisArg) {
7598
      var computed = -Infinity,
7599
          result = computed;
7600

    
7601
      // allows working with functions like `_.map` without using
7602
      // their `index` argument as a callback
7603
      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
7604
        callback = null;
7605
      }
7606
      if (callback == null && isArray(collection)) {
7607
        var index = -1,
7608
            length = collection.length;
7609

    
7610
        while (++index < length) {
7611
          var value = collection[index];
7612
          if (value > result) {
7613
            result = value;
7614
          }
7615
        }
7616
      } else {
7617
        callback = (callback == null && isString(collection))
7618
          ? charAtCallback
7619
          : lodash.createCallback(callback, thisArg, 3);
7620

    
7621
        forEach(collection, function(value, index, collection) {
7622
          var current = callback(value, index, collection);
7623
          if (current > computed) {
7624
            computed = current;
7625
            result = value;
7626
          }
7627
        });
7628
      }
7629
      return result;
7630
    }
7631

    
7632
    /**
7633
     * Retrieves the minimum value of a collection. If the collection is empty or
7634
     * falsey `Infinity` is returned. If a callback is provided it will be executed
7635
     * for each value in the collection to generate the criterion by which the value
7636
     * is ranked. The callback is bound to `thisArg` and invoked with three
7637
     * arguments; (value, index, collection).
7638
     *
7639
     * If a property name is provided for `callback` the created "_.pluck" style
7640
     * callback will return the property value of the given element.
7641
     *
7642
     * If an object is provided for `callback` the created "_.where" style callback
7643
     * will return `true` for elements that have the properties of the given object,
7644
     * else `false`.
7645
     *
7646
     * @static
7647
     * @memberOf _
7648
     * @category Collections
7649
     * @param {Array|Object|string} collection The collection to iterate over.
7650
     * @param {Function|Object|string} [callback=identity] The function called
7651
     *  per iteration. If a property name or object is provided it will be used
7652
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7653
     * @param {*} [thisArg] The `this` binding of `callback`.
7654
     * @returns {*} Returns the minimum value.
7655
     * @example
7656
     *
7657
     * _.min([4, 2, 8, 6]);
7658
     * // => 2
7659
     *
7660
     * var characters = [
7661
     *   { 'name': 'barney', 'age': 36 },
7662
     *   { 'name': 'fred',   'age': 40 }
7663
     * ];
7664
     *
7665
     * _.min(characters, function(chr) { return chr.age; });
7666
     * // => { 'name': 'barney', 'age': 36 };
7667
     *
7668
     * // using "_.pluck" callback shorthand
7669
     * _.min(characters, 'age');
7670
     * // => { 'name': 'barney', 'age': 36 };
7671
     */
7672
    function min(collection, callback, thisArg) {
7673
      var computed = Infinity,
7674
          result = computed;
7675

    
7676
      // allows working with functions like `_.map` without using
7677
      // their `index` argument as a callback
7678
      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
7679
        callback = null;
7680
      }
7681
      if (callback == null && isArray(collection)) {
7682
        var index = -1,
7683
            length = collection.length;
7684

    
7685
        while (++index < length) {
7686
          var value = collection[index];
7687
          if (value < result) {
7688
            result = value;
7689
          }
7690
        }
7691
      } else {
7692
        callback = (callback == null && isString(collection))
7693
          ? charAtCallback
7694
          : lodash.createCallback(callback, thisArg, 3);
7695

    
7696
        forEach(collection, function(value, index, collection) {
7697
          var current = callback(value, index, collection);
7698
          if (current < computed) {
7699
            computed = current;
7700
            result = value;
7701
          }
7702
        });
7703
      }
7704
      return result;
7705
    }
7706

    
7707
    /**
7708
     * Retrieves the value of a specified property from all elements in the collection.
7709
     *
7710
     * @static
7711
     * @memberOf _
7712
     * @type Function
7713
     * @category Collections
7714
     * @param {Array|Object|string} collection The collection to iterate over.
7715
     * @param {string} property The name of the property to pluck.
7716
     * @returns {Array} Returns a new array of property values.
7717
     * @example
7718
     *
7719
     * var characters = [
7720
     *   { 'name': 'barney', 'age': 36 },
7721
     *   { 'name': 'fred',   'age': 40 }
7722
     * ];
7723
     *
7724
     * _.pluck(characters, 'name');
7725
     * // => ['barney', 'fred']
7726
     */
7727
    var pluck = map;
7728

    
7729
    /**
7730
     * Reduces a collection to a value which is the accumulated result of running
7731
     * each element in the collection through the callback, where each successive
7732
     * callback execution consumes the return value of the previous execution. If
7733
     * `accumulator` is not provided the first element of the collection will be
7734
     * used as the initial `accumulator` value. The callback is bound to `thisArg`
7735
     * and invoked with four arguments; (accumulator, value, index|key, collection).
7736
     *
7737
     * @static
7738
     * @memberOf _
7739
     * @alias foldl, inject
7740
     * @category Collections
7741
     * @param {Array|Object|string} collection The collection to iterate over.
7742
     * @param {Function} [callback=identity] The function called per iteration.
7743
     * @param {*} [accumulator] Initial value of the accumulator.
7744
     * @param {*} [thisArg] The `this` binding of `callback`.
7745
     * @returns {*} Returns the accumulated value.
7746
     * @example
7747
     *
7748
     * var sum = _.reduce([1, 2, 3], function(sum, num) {
7749
     *   return sum + num;
7750
     * });
7751
     * // => 6
7752
     *
7753
     * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
7754
     *   result[key] = num * 3;
7755
     *   return result;
7756
     * }, {});
7757
     * // => { 'a': 3, 'b': 6, 'c': 9 }
7758
     */
7759
    function reduce(collection, callback, accumulator, thisArg) {
7760
      if (!collection) return accumulator;
7761
      var noaccum = arguments.length < 3;
7762
      callback = lodash.createCallback(callback, thisArg, 4);
7763

    
7764
      var index = -1,
7765
          length = collection.length;
7766

    
7767
      if (typeof length == 'number') {
7768
        if (noaccum) {
7769
          accumulator = collection[++index];
7770
        }
7771
        while (++index < length) {
7772
          accumulator = callback(accumulator, collection[index], index, collection);
7773
        }
7774
      } else {
7775
        forOwn(collection, function(value, index, collection) {
7776
          accumulator = noaccum
7777
            ? (noaccum = false, value)
7778
            : callback(accumulator, value, index, collection)
7779
        });
7780
      }
7781
      return accumulator;
7782
    }
7783

    
7784
    /**
7785
     * This method is like `_.reduce` except that it iterates over elements
7786
     * of a `collection` from right to left.
7787
     *
7788
     * @static
7789
     * @memberOf _
7790
     * @alias foldr
7791
     * @category Collections
7792
     * @param {Array|Object|string} collection The collection to iterate over.
7793
     * @param {Function} [callback=identity] The function called per iteration.
7794
     * @param {*} [accumulator] Initial value of the accumulator.
7795
     * @param {*} [thisArg] The `this` binding of `callback`.
7796
     * @returns {*} Returns the accumulated value.
7797
     * @example
7798
     *
7799
     * var list = [[0, 1], [2, 3], [4, 5]];
7800
     * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
7801
     * // => [4, 5, 2, 3, 0, 1]
7802
     */
7803
    function reduceRight(collection, callback, accumulator, thisArg) {
7804
      var noaccum = arguments.length < 3;
7805
      callback = lodash.createCallback(callback, thisArg, 4);
7806
      forEachRight(collection, function(value, index, collection) {
7807
        accumulator = noaccum
7808
          ? (noaccum = false, value)
7809
          : callback(accumulator, value, index, collection);
7810
      });
7811
      return accumulator;
7812
    }
7813

    
7814
    /**
7815
     * The opposite of `_.filter` this method returns the elements of a
7816
     * collection that the callback does **not** return truey for.
7817
     *
7818
     * If a property name is provided for `callback` the created "_.pluck" style
7819
     * callback will return the property value of the given element.
7820
     *
7821
     * If an object is provided for `callback` the created "_.where" style callback
7822
     * will return `true` for elements that have the properties of the given object,
7823
     * else `false`.
7824
     *
7825
     * @static
7826
     * @memberOf _
7827
     * @category Collections
7828
     * @param {Array|Object|string} collection The collection to iterate over.
7829
     * @param {Function|Object|string} [callback=identity] The function called
7830
     *  per iteration. If a property name or object is provided it will be used
7831
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7832
     * @param {*} [thisArg] The `this` binding of `callback`.
7833
     * @returns {Array} Returns a new array of elements that failed the callback check.
7834
     * @example
7835
     *
7836
     * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
7837
     * // => [1, 3, 5]
7838
     *
7839
     * var characters = [
7840
     *   { 'name': 'barney', 'age': 36, 'blocked': false },
7841
     *   { 'name': 'fred',   'age': 40, 'blocked': true }
7842
     * ];
7843
     *
7844
     * // using "_.pluck" callback shorthand
7845
     * _.reject(characters, 'blocked');
7846
     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
7847
     *
7848
     * // using "_.where" callback shorthand
7849
     * _.reject(characters, { 'age': 36 });
7850
     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
7851
     */
7852
    function reject(collection, callback, thisArg) {
7853
      callback = lodash.createCallback(callback, thisArg, 3);
7854
      return filter(collection, function(value, index, collection) {
7855
        return !callback(value, index, collection);
7856
      });
7857
    }
7858

    
7859
    /**
7860
     * Retrieves a random element or `n` random elements from a collection.
7861
     *
7862
     * @static
7863
     * @memberOf _
7864
     * @category Collections
7865
     * @param {Array|Object|string} collection The collection to sample.
7866
     * @param {number} [n] The number of elements to sample.
7867
     * @param- {Object} [guard] Allows working with functions like `_.map`
7868
     *  without using their `index` arguments as `n`.
7869
     * @returns {Array} Returns the random sample(s) of `collection`.
7870
     * @example
7871
     *
7872
     * _.sample([1, 2, 3, 4]);
7873
     * // => 2
7874
     *
7875
     * _.sample([1, 2, 3, 4], 2);
7876
     * // => [3, 1]
7877
     */
7878
    function sample(collection, n, guard) {
7879
      if (collection && typeof collection.length != 'number') {
7880
        collection = values(collection);
7881
      }
7882
      if (n == null || guard) {
7883
        return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
7884
      }
7885
      var result = shuffle(collection);
7886
      result.length = nativeMin(nativeMax(0, n), result.length);
7887
      return result;
7888
    }
7889

    
7890
    /**
7891
     * Creates an array of shuffled values, using a version of the Fisher-Yates
7892
     * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
7893
     *
7894
     * @static
7895
     * @memberOf _
7896
     * @category Collections
7897
     * @param {Array|Object|string} collection The collection to shuffle.
7898
     * @returns {Array} Returns a new shuffled collection.
7899
     * @example
7900
     *
7901
     * _.shuffle([1, 2, 3, 4, 5, 6]);
7902
     * // => [4, 1, 6, 3, 5, 2]
7903
     */
7904
    function shuffle(collection) {
7905
      var index = -1,
7906
          length = collection ? collection.length : 0,
7907
          result = Array(typeof length == 'number' ? length : 0);
7908

    
7909
      forEach(collection, function(value) {
7910
        var rand = baseRandom(0, ++index);
7911
        result[index] = result[rand];
7912
        result[rand] = value;
7913
      });
7914
      return result;
7915
    }
7916

    
7917
    /**
7918
     * Gets the size of the `collection` by returning `collection.length` for arrays
7919
     * and array-like objects or the number of own enumerable properties for objects.
7920
     *
7921
     * @static
7922
     * @memberOf _
7923
     * @category Collections
7924
     * @param {Array|Object|string} collection The collection to inspect.
7925
     * @returns {number} Returns `collection.length` or number of own enumerable properties.
7926
     * @example
7927
     *
7928
     * _.size([1, 2]);
7929
     * // => 2
7930
     *
7931
     * _.size({ 'one': 1, 'two': 2, 'three': 3 });
7932
     * // => 3
7933
     *
7934
     * _.size('pebbles');
7935
     * // => 7
7936
     */
7937
    function size(collection) {
7938
      var length = collection ? collection.length : 0;
7939
      return typeof length == 'number' ? length : keys(collection).length;
7940
    }
7941

    
7942
    /**
7943
     * Checks if the callback returns a truey value for **any** element of a
7944
     * collection. The function returns as soon as it finds a passing value and
7945
     * does not iterate over the entire collection. The callback is bound to
7946
     * `thisArg` and invoked with three arguments; (value, index|key, collection).
7947
     *
7948
     * If a property name is provided for `callback` the created "_.pluck" style
7949
     * callback will return the property value of the given element.
7950
     *
7951
     * If an object is provided for `callback` the created "_.where" style callback
7952
     * will return `true` for elements that have the properties of the given object,
7953
     * else `false`.
7954
     *
7955
     * @static
7956
     * @memberOf _
7957
     * @alias any
7958
     * @category Collections
7959
     * @param {Array|Object|string} collection The collection to iterate over.
7960
     * @param {Function|Object|string} [callback=identity] The function called
7961
     *  per iteration. If a property name or object is provided it will be used
7962
     *  to create a "_.pluck" or "_.where" style callback, respectively.
7963
     * @param {*} [thisArg] The `this` binding of `callback`.
7964
     * @returns {boolean} Returns `true` if any element passed the callback check,
7965
     *  else `false`.
7966
     * @example
7967
     *
7968
     * _.some([null, 0, 'yes', false], Boolean);
7969
     * // => true
7970
     *
7971
     * var characters = [
7972
     *   { 'name': 'barney', 'age': 36, 'blocked': false },
7973
     *   { 'name': 'fred',   'age': 40, 'blocked': true }
7974
     * ];
7975
     *
7976
     * // using "_.pluck" callback shorthand
7977
     * _.some(characters, 'blocked');
7978
     * // => true
7979
     *
7980
     * // using "_.where" callback shorthand
7981
     * _.some(characters, { 'age': 1 });
7982
     * // => false
7983
     */
7984
    function some(collection, callback, thisArg) {
7985
      var result;
7986
      callback = lodash.createCallback(callback, thisArg, 3);
7987

    
7988
      var index = -1,
7989
          length = collection ? collection.length : 0;
7990

    
7991
      if (typeof length == 'number') {
7992
        while (++index < length) {
7993
          if ((result = callback(collection[index], index, collection))) {
7994
            break;
7995
          }
7996
        }
7997
      } else {
7998
        forOwn(collection, function(value, index, collection) {
7999
          return !(result = callback(value, index, collection));
8000
        });
8001
      }
8002
      return !!result;
8003
    }
8004

    
8005
    /**
8006
     * Creates an array of elements, sorted in ascending order by the results of
8007
     * running each element in a collection through the callback. This method
8008
     * performs a stable sort, that is, it will preserve the original sort order
8009
     * of equal elements. The callback is bound to `thisArg` and invoked with
8010
     * three arguments; (value, index|key, collection).
8011
     *
8012
     * If a property name is provided for `callback` the created "_.pluck" style
8013
     * callback will return the property value of the given element.
8014
     *
8015
     * If an array of property names is provided for `callback` the collection
8016
     * will be sorted by each property value.
8017
     *
8018
     * If an object is provided for `callback` the created "_.where" style callback
8019
     * will return `true` for elements that have the properties of the given object,
8020
     * else `false`.
8021
     *
8022
     * @static
8023
     * @memberOf _
8024
     * @category Collections
8025
     * @param {Array|Object|string} collection The collection to iterate over.
8026
     * @param {Array|Function|Object|string} [callback=identity] The function called
8027
     *  per iteration. If a property name or object is provided it will be used
8028
     *  to create a "_.pluck" or "_.where" style callback, respectively.
8029
     * @param {*} [thisArg] The `this` binding of `callback`.
8030
     * @returns {Array} Returns a new array of sorted elements.
8031
     * @example
8032
     *
8033
     * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
8034
     * // => [3, 1, 2]
8035
     *
8036
     * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
8037
     * // => [3, 1, 2]
8038
     *
8039
     * var characters = [
8040
     *   { 'name': 'barney',  'age': 36 },
8041
     *   { 'name': 'fred',    'age': 40 },
8042
     *   { 'name': 'barney',  'age': 26 },
8043
     *   { 'name': 'fred',    'age': 30 }
8044
     * ];
8045
     *
8046
     * // using "_.pluck" callback shorthand
8047
     * _.map(_.sortBy(characters, 'age'), _.values);
8048
     * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
8049
     *
8050
     * // sorting by multiple properties
8051
     * _.map(_.sortBy(characters, ['name', 'age']), _.values);
8052
     * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
8053
     */
8054
    function sortBy(collection, callback, thisArg) {
8055
      var index = -1,
8056
          isArr = isArray(callback),
8057
          length = collection ? collection.length : 0,
8058
          result = Array(typeof length == 'number' ? length : 0);
8059

    
8060
      if (!isArr) {
8061
        callback = lodash.createCallback(callback, thisArg, 3);
8062
      }
8063
      forEach(collection, function(value, key, collection) {
8064
        var object = result[++index] = getObject();
8065
        if (isArr) {
8066
          object.criteria = map(callback, function(key) { return value[key]; });
8067
        } else {
8068
          (object.criteria = getArray())[0] = callback(value, key, collection);
8069
        }
8070
        object.index = index;
8071
        object.value = value;
8072
      });
8073

    
8074
      length = result.length;
8075
      result.sort(compareAscending);
8076
      while (length--) {
8077
        var object = result[length];
8078
        result[length] = object.value;
8079
        if (!isArr) {
8080
          releaseArray(object.criteria);
8081
        }
8082
        releaseObject(object);
8083
      }
8084
      return result;
8085
    }
8086

    
8087
    /**
8088
     * Converts the `collection` to an array.
8089
     *
8090
     * @static
8091
     * @memberOf _
8092
     * @category Collections
8093
     * @param {Array|Object|string} collection The collection to convert.
8094
     * @returns {Array} Returns the new converted array.
8095
     * @example
8096
     *
8097
     * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
8098
     * // => [2, 3, 4]
8099
     */
8100
    function toArray(collection) {
8101
      if (collection && typeof collection.length == 'number') {
8102
        return slice(collection);
8103
      }
8104
      return values(collection);
8105
    }
8106

    
8107
    /**
8108
     * Performs a deep comparison of each element in a `collection` to the given
8109
     * `properties` object, returning an array of all elements that have equivalent
8110
     * property values.
8111
     *
8112
     * @static
8113
     * @memberOf _
8114
     * @type Function
8115
     * @category Collections
8116
     * @param {Array|Object|string} collection The collection to iterate over.
8117
     * @param {Object} props The object of property values to filter by.
8118
     * @returns {Array} Returns a new array of elements that have the given properties.
8119
     * @example
8120
     *
8121
     * var characters = [
8122
     *   { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
8123
     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
8124
     * ];
8125
     *
8126
     * _.where(characters, { 'age': 36 });
8127
     * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
8128
     *
8129
     * _.where(characters, { 'pets': ['dino'] });
8130
     * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
8131
     */
8132
    var where = filter;
8133

    
8134
    /*--------------------------------------------------------------------------*/
8135

    
8136
    /**
8137
     * Creates an array with all falsey values removed. The values `false`, `null`,
8138
     * `0`, `""`, `undefined`, and `NaN` are all falsey.
8139
     *
8140
     * @static
8141
     * @memberOf _
8142
     * @category Arrays
8143
     * @param {Array} array The array to compact.
8144
     * @returns {Array} Returns a new array of filtered values.
8145
     * @example
8146
     *
8147
     * _.compact([0, 1, false, 2, '', 3]);
8148
     * // => [1, 2, 3]
8149
     */
8150
    function compact(array) {
8151
      var index = -1,
8152
          length = array ? array.length : 0,
8153
          result = [];
8154

    
8155
      while (++index < length) {
8156
        var value = array[index];
8157
        if (value) {
8158
          result.push(value);
8159
        }
8160
      }
8161
      return result;
8162
    }
8163

    
8164
    /**
8165
     * Creates an array excluding all values of the provided arrays using strict
8166
     * equality for comparisons, i.e. `===`.
8167
     *
8168
     * @static
8169
     * @memberOf _
8170
     * @category Arrays
8171
     * @param {Array} array The array to process.
8172
     * @param {...Array} [values] The arrays of values to exclude.
8173
     * @returns {Array} Returns a new array of filtered values.
8174
     * @example
8175
     *
8176
     * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
8177
     * // => [1, 3, 4]
8178
     */
8179
    function difference(array) {
8180
      return baseDifference(array, baseFlatten(arguments, true, true, 1));
8181
    }
8182

    
8183
    /**
8184
     * This method is like `_.find` except that it returns the index of the first
8185
     * element that passes the callback check, instead of the element itself.
8186
     *
8187
     * If a property name is provided for `callback` the created "_.pluck" style
8188
     * callback will return the property value of the given element.
8189
     *
8190
     * If an object is provided for `callback` the created "_.where" style callback
8191
     * will return `true` for elements that have the properties of the given object,
8192
     * else `false`.
8193
     *
8194
     * @static
8195
     * @memberOf _
8196
     * @category Arrays
8197
     * @param {Array} array The array to search.
8198
     * @param {Function|Object|string} [callback=identity] The function called
8199
     *  per iteration. If a property name or object is provided it will be used
8200
     *  to create a "_.pluck" or "_.where" style callback, respectively.
8201
     * @param {*} [thisArg] The `this` binding of `callback`.
8202
     * @returns {number} Returns the index of the found element, else `-1`.
8203
     * @example
8204
     *
8205
     * var characters = [
8206
     *   { 'name': 'barney',  'age': 36, 'blocked': false },
8207
     *   { 'name': 'fred',    'age': 40, 'blocked': true },
8208
     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
8209
     * ];
8210
     *
8211
     * _.findIndex(characters, function(chr) {
8212
     *   return chr.age < 20;
8213
     * });
8214
     * // => 2
8215
     *
8216
     * // using "_.where" callback shorthand
8217
     * _.findIndex(characters, { 'age': 36 });
8218
     * // => 0
8219
     *
8220
     * // using "_.pluck" callback shorthand
8221
     * _.findIndex(characters, 'blocked');
8222
     * // => 1
8223
     */
8224
    function findIndex(array, callback, thisArg) {
8225
      var index = -1,
8226
          length = array ? array.length : 0;
8227

    
8228
      callback = lodash.createCallback(callback, thisArg, 3);
8229
      while (++index < length) {
8230
        if (callback(array[index], index, array)) {
8231
          return index;
8232
        }
8233
      }
8234
      return -1;
8235
    }
8236

    
8237
    /**
8238
     * This method is like `_.findIndex` except that it iterates over elements
8239
     * of a `collection` from right to left.
8240
     *
8241
     * If a property name is provided for `callback` the created "_.pluck" style
8242
     * callback will return the property value of the given element.
8243
     *
8244
     * If an object is provided for `callback` the created "_.where" style callback
8245
     * will return `true` for elements that have the properties of the given object,
8246
     * else `false`.
8247
     *
8248
     * @static
8249
     * @memberOf _
8250
     * @category Arrays
8251
     * @param {Array} array The array to search.
8252
     * @param {Function|Object|string} [callback=identity] The function called
8253
     *  per iteration. If a property name or object is provided it will be used
8254
     *  to create a "_.pluck" or "_.where" style callback, respectively.
8255
     * @param {*} [thisArg] The `this` binding of `callback`.
8256
     * @returns {number} Returns the index of the found element, else `-1`.
8257
     * @example
8258
     *
8259
     * var characters = [
8260
     *   { 'name': 'barney',  'age': 36, 'blocked': true },
8261
     *   { 'name': 'fred',    'age': 40, 'blocked': false },
8262
     *   { 'name': 'pebbles', 'age': 1,  'blocked': true }
8263
     * ];
8264
     *
8265
     * _.findLastIndex(characters, function(chr) {
8266
     *   return chr.age > 30;
8267
     * });
8268
     * // => 1
8269
     *
8270
     * // using "_.where" callback shorthand
8271
     * _.findLastIndex(characters, { 'age': 36 });
8272
     * // => 0
8273
     *
8274
     * // using "_.pluck" callback shorthand
8275
     * _.findLastIndex(characters, 'blocked');
8276
     * // => 2
8277
     */
8278
    function findLastIndex(array, callback, thisArg) {
8279
      var length = array ? array.length : 0;
8280
      callback = lodash.createCallback(callback, thisArg, 3);
8281
      while (length--) {
8282
        if (callback(array[length], length, array)) {
8283
          return length;
8284
        }
8285
      }
8286
      return -1;
8287
    }
8288

    
8289
    /**
8290
     * Gets the first element or first `n` elements of an array. If a callback
8291
     * is provided elements at the beginning of the array are returned as long
8292
     * as the callback returns truey. The callback is bound to `thisArg` and
8293
     * invoked with three arguments; (value, index, array).
8294
     *
8295
     * If a property name is provided for `callback` the created "_.pluck" style
8296
     * callback will return the property value of the given element.
8297
     *
8298
     * If an object is provided for `callback` the created "_.where" style callback
8299
     * will return `true` for elements that have the properties of the given object,
8300
     * else `false`.
8301
     *
8302
     * @static
8303
     * @memberOf _
8304
     * @alias head, take
8305
     * @category Arrays
8306
     * @param {Array} array The array to query.
8307
     * @param {Function|Object|number|string} [callback] The function called
8308
     *  per element or the number of elements to return. If a property name or
8309
     *  object is provided it will be used to create a "_.pluck" or "_.where"
8310
     *  style callback, respectively.
8311
     * @param {*} [thisArg] The `this` binding of `callback`.
8312
     * @returns {*} Returns the first element(s) of `array`.
8313
     * @example
8314
     *
8315
     * _.first([1, 2, 3]);
8316
     * // => 1
8317
     *
8318
     * _.first([1, 2, 3], 2);
8319
     * // => [1, 2]
8320
     *
8321
     * _.first([1, 2, 3], function(num) {
8322
     *   return num < 3;
8323
     * });
8324
     * // => [1, 2]
8325
     *
8326
     * var characters = [
8327
     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
8328
     *   { 'name': 'fred',    'blocked': false, 'employer': 'slate' },
8329
     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
8330
     * ];
8331
     *
8332
     * // using "_.pluck" callback shorthand
8333
     * _.first(characters, 'blocked');
8334
     * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
8335
     *
8336
     * // using "_.where" callback shorthand
8337
     * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
8338
     * // => ['barney', 'fred']
8339
     */
8340
    function first(array, callback, thisArg) {
8341
      var n = 0,
8342
          length = array ? array.length : 0;
8343

    
8344
      if (typeof callback != 'number' && callback != null) {
8345
        var index = -1;
8346
        callback = lodash.createCallback(callback, thisArg, 3);
8347
        while (++index < length && callback(array[index], index, array)) {
8348
          n++;
8349
        }
8350
      } else {
8351
        n = callback;
8352
        if (n == null || thisArg) {
8353
          return array ? array[0] : undefined;
8354
        }
8355
      }
8356
      return slice(array, 0, nativeMin(nativeMax(0, n), length));
8357
    }
8358

    
8359
    /**
8360
     * Flattens a nested array (the nesting can be to any depth). If `isShallow`
8361
     * is truey, the array will only be flattened a single level. If a callback
8362
     * is provided each element of the array is passed through the callback before
8363
     * flattening. The callback is bound to `thisArg` and invoked with three
8364
     * arguments; (value, index, array).
8365
     *
8366
     * If a property name is provided for `callback` the created "_.pluck" style
8367
     * callback will return the property value of the given element.
8368
     *
8369
     * If an object is provided for `callback` the created "_.where" style callback
8370
     * will return `true` for elements that have the properties of the given object,
8371
     * else `false`.
8372
     *
8373
     * @static
8374
     * @memberOf _
8375
     * @category Arrays
8376
     * @param {Array} array The array to flatten.
8377
     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
8378
     * @param {Function|Object|string} [callback=identity] The function called
8379
     *  per iteration. If a property name or object is provided it will be used
8380
     *  to create a "_.pluck" or "_.where" style callback, respectively.
8381
     * @param {*} [thisArg] The `this` binding of `callback`.
8382
     * @returns {Array} Returns a new flattened array.
8383
     * @example
8384
     *
8385
     * _.flatten([1, [2], [3, [[4]]]]);
8386
     * // => [1, 2, 3, 4];
8387
     *
8388
     * _.flatten([1, [2], [3, [[4]]]], true);
8389
     * // => [1, 2, 3, [[4]]];
8390
     *
8391
     * var characters = [
8392
     *   { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
8393
     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
8394
     * ];
8395
     *
8396
     * // using "_.pluck" callback shorthand
8397
     * _.flatten(characters, 'pets');
8398
     * // => ['hoppy', 'baby puss', 'dino']
8399
     */
8400
    function flatten(array, isShallow, callback, thisArg) {
8401
      // juggle arguments
8402
      if (typeof isShallow != 'boolean' && isShallow != null) {
8403
        thisArg = callback;
8404
        callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
8405
        isShallow = false;
8406
      }
8407
      if (callback != null) {
8408
        array = map(array, callback, thisArg);
8409
      }
8410
      return baseFlatten(array, isShallow);
8411
    }
8412

    
8413
    /**
8414
     * Gets the index at which the first occurrence of `value` is found using
8415
     * strict equality for comparisons, i.e. `===`. If the array is already sorted
8416
     * providing `true` for `fromIndex` will run a faster binary search.
8417
     *
8418
     * @static
8419
     * @memberOf _
8420
     * @category Arrays
8421
     * @param {Array} array The array to search.
8422
     * @param {*} value The value to search for.
8423
     * @param {boolean|number} [fromIndex=0] The index to search from or `true`
8424
     *  to perform a binary search on a sorted array.
8425
     * @returns {number} Returns the index of the matched value or `-1`.
8426
     * @example
8427
     *
8428
     * _.indexOf([1, 2, 3, 1, 2, 3], 2);
8429
     * // => 1
8430
     *
8431
     * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
8432
     * // => 4
8433
     *
8434
     * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
8435
     * // => 2
8436
     */
8437
    function indexOf(array, value, fromIndex) {
8438
      if (typeof fromIndex == 'number') {
8439
        var length = array ? array.length : 0;
8440
        fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
8441
      } else if (fromIndex) {
8442
        var index = sortedIndex(array, value);
8443
        return array[index] === value ? index : -1;
8444
      }
8445
      return baseIndexOf(array, value, fromIndex);
8446
    }
8447

    
8448
    /**
8449
     * Gets all but the last element or last `n` elements of an array. If a
8450
     * callback is provided elements at the end of the array are excluded from
8451
     * the result as long as the callback returns truey. The callback is bound
8452
     * to `thisArg` and invoked with three arguments; (value, index, array).
8453
     *
8454
     * If a property name is provided for `callback` the created "_.pluck" style
8455
     * callback will return the property value of the given element.
8456
     *
8457
     * If an object is provided for `callback` the created "_.where" style callback
8458
     * will return `true` for elements that have the properties of the given object,
8459
     * else `false`.
8460
     *
8461
     * @static
8462
     * @memberOf _
8463
     * @category Arrays
8464
     * @param {Array} array The array to query.
8465
     * @param {Function|Object|number|string} [callback=1] The function called
8466
     *  per element or the number of elements to exclude. If a property name or
8467
     *  object is provided it will be used to create a "_.pluck" or "_.where"
8468
     *  style callback, respectively.
8469
     * @param {*} [thisArg] The `this` binding of `callback`.
8470
     * @returns {Array} Returns a slice of `array`.
8471
     * @example
8472
     *
8473
     * _.initial([1, 2, 3]);
8474
     * // => [1, 2]
8475
     *
8476
     * _.initial([1, 2, 3], 2);
8477
     * // => [1]
8478
     *
8479
     * _.initial([1, 2, 3], function(num) {
8480
     *   return num > 1;
8481
     * });
8482
     * // => [1]
8483
     *
8484
     * var characters = [
8485
     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
8486
     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
8487
     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
8488
     * ];
8489
     *
8490
     * // using "_.pluck" callback shorthand
8491
     * _.initial(characters, 'blocked');
8492
     * // => [{ 'name': 'barney',  'blocked': false, 'employer': 'slate' }]
8493
     *
8494
     * // using "_.where" callback shorthand
8495
     * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
8496
     * // => ['barney', 'fred']
8497
     */
8498
    function initial(array, callback, thisArg) {
8499
      var n = 0,
8500
          length = array ? array.length : 0;
8501

    
8502
      if (typeof callback != 'number' && callback != null) {
8503
        var index = length;
8504
        callback = lodash.createCallback(callback, thisArg, 3);
8505
        while (index-- && callback(array[index], index, array)) {
8506
          n++;
8507
        }
8508
      } else {
8509
        n = (callback == null || thisArg) ? 1 : callback || n;
8510
      }
8511
      return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
8512
    }
8513

    
8514
    /**
8515
     * Creates an array of unique values present in all provided arrays using
8516
     * strict equality for comparisons, i.e. `===`.
8517
     *
8518
     * @static
8519
     * @memberOf _
8520
     * @category Arrays
8521
     * @param {...Array} [array] The arrays to inspect.
8522
     * @returns {Array} Returns an array of shared values.
8523
     * @example
8524
     *
8525
     * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
8526
     * // => [1, 2]
8527
     */
8528
    function intersection() {
8529
      var args = [],
8530
          argsIndex = -1,
8531
          argsLength = arguments.length,
8532
          caches = getArray(),
8533
          indexOf = getIndexOf(),
8534
          trustIndexOf = indexOf === baseIndexOf,
8535
          seen = getArray();
8536

    
8537
      while (++argsIndex < argsLength) {
8538
        var value = arguments[argsIndex];
8539
        if (isArray(value) || isArguments(value)) {
8540
          args.push(value);
8541
          caches.push(trustIndexOf && value.length >= largeArraySize &&
8542
            createCache(argsIndex ? args[argsIndex] : seen));
8543
        }
8544
      }
8545
      var array = args[0],
8546
          index = -1,
8547
          length = array ? array.length : 0,
8548
          result = [];
8549

    
8550
      outer:
8551
      while (++index < length) {
8552
        var cache = caches[0];
8553
        value = array[index];
8554

    
8555
        if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
8556
          argsIndex = argsLength;
8557
          (cache || seen).push(value);
8558
          while (--argsIndex) {
8559
            cache = caches[argsIndex];
8560
            if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
8561
              continue outer;
8562
            }
8563
          }
8564
          result.push(value);
8565
        }
8566
      }
8567
      while (argsLength--) {
8568
        cache = caches[argsLength];
8569
        if (cache) {
8570
          releaseObject(cache);
8571
        }
8572
      }
8573
      releaseArray(caches);
8574
      releaseArray(seen);
8575
      return result;
8576
    }
8577

    
8578
    /**
8579
     * Gets the last element or last `n` elements of an array. If a callback is
8580
     * provided elements at the end of the array are returned as long as the
8581
     * callback returns truey. The callback is bound to `thisArg` and invoked
8582
     * with three arguments; (value, index, array).
8583
     *
8584
     * If a property name is provided for `callback` the created "_.pluck" style
8585
     * callback will return the property value of the given element.
8586
     *
8587
     * If an object is provided for `callback` the created "_.where" style callback
8588
     * will return `true` for elements that have the properties of the given object,
8589
     * else `false`.
8590
     *
8591
     * @static
8592
     * @memberOf _
8593
     * @category Arrays
8594
     * @param {Array} array The array to query.
8595
     * @param {Function|Object|number|string} [callback] The function called
8596
     *  per element or the number of elements to return. If a property name or
8597
     *  object is provided it will be used to create a "_.pluck" or "_.where"
8598
     *  style callback, respectively.
8599
     * @param {*} [thisArg] The `this` binding of `callback`.
8600
     * @returns {*} Returns the last element(s) of `array`.
8601
     * @example
8602
     *
8603
     * _.last([1, 2, 3]);
8604
     * // => 3
8605
     *
8606
     * _.last([1, 2, 3], 2);
8607
     * // => [2, 3]
8608
     *
8609
     * _.last([1, 2, 3], function(num) {
8610
     *   return num > 1;
8611
     * });
8612
     * // => [2, 3]
8613
     *
8614
     * var characters = [
8615
     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
8616
     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
8617
     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
8618
     * ];
8619
     *
8620
     * // using "_.pluck" callback shorthand
8621
     * _.pluck(_.last(characters, 'blocked'), 'name');
8622
     * // => ['fred', 'pebbles']
8623
     *
8624
     * // using "_.where" callback shorthand
8625
     * _.last(characters, { 'employer': 'na' });
8626
     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
8627
     */
8628
    function last(array, callback, thisArg) {
8629
      var n = 0,
8630
          length = array ? array.length : 0;
8631

    
8632
      if (typeof callback != 'number' && callback != null) {
8633
        var index = length;
8634
        callback = lodash.createCallback(callback, thisArg, 3);
8635
        while (index-- && callback(array[index], index, array)) {
8636
          n++;
8637
        }
8638
      } else {
8639
        n = callback;
8640
        if (n == null || thisArg) {
8641
          return array ? array[length - 1] : undefined;
8642
        }
8643
      }
8644
      return slice(array, nativeMax(0, length - n));
8645
    }
8646

    
8647
    /**
8648
     * Gets the index at which the last occurrence of `value` is found using strict
8649
     * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
8650
     * as the offset from the end of the collection.
8651
     *
8652
     * If a property name is provided for `callback` the created "_.pluck" style
8653
     * callback will return the property value of the given element.
8654
     *
8655
     * If an object is provided for `callback` the created "_.where" style callback
8656
     * will return `true` for elements that have the properties of the given object,
8657
     * else `false`.
8658
     *
8659
     * @static
8660
     * @memberOf _
8661
     * @category Arrays
8662
     * @param {Array} array The array to search.
8663
     * @param {*} value The value to search for.
8664
     * @param {number} [fromIndex=array.length-1] The index to search from.
8665
     * @returns {number} Returns the index of the matched value or `-1`.
8666
     * @example
8667
     *
8668
     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
8669
     * // => 4
8670
     *
8671
     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
8672
     * // => 1
8673
     */
8674
    function lastIndexOf(array, value, fromIndex) {
8675
      var index = array ? array.length : 0;
8676
      if (typeof fromIndex == 'number') {
8677
        index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
8678
      }
8679
      while (index--) {
8680
        if (array[index] === value) {
8681
          return index;
8682
        }
8683
      }
8684
      return -1;
8685
    }
8686

    
8687
    /**
8688
     * Removes all provided values from the given array using strict equality for
8689
     * comparisons, i.e. `===`.
8690
     *
8691
     * @static
8692
     * @memberOf _
8693
     * @category Arrays
8694
     * @param {Array} array The array to modify.
8695
     * @param {...*} [value] The values to remove.
8696
     * @returns {Array} Returns `array`.
8697
     * @example
8698
     *
8699
     * var array = [1, 2, 3, 1, 2, 3];
8700
     * _.pull(array, 2, 3);
8701
     * console.log(array);
8702
     * // => [1, 1]
8703
     */
8704
    function pull(array) {
8705
      var args = arguments,
8706
          argsIndex = 0,
8707
          argsLength = args.length,
8708
          length = array ? array.length : 0;
8709

    
8710
      while (++argsIndex < argsLength) {
8711
        var index = -1,
8712
            value = args[argsIndex];
8713
        while (++index < length) {
8714
          if (array[index] === value) {
8715
            splice.call(array, index--, 1);
8716
            length--;
8717
          }
8718
        }
8719
      }
8720
      return array;
8721
    }
8722

    
8723
    /**
8724
     * Creates an array of numbers (positive and/or negative) progressing from
8725
     * `start` up to but not including `end`. If `start` is less than `stop` a
8726
     * zero-length range is created unless a negative `step` is specified.
8727
     *
8728
     * @static
8729
     * @memberOf _
8730
     * @category Arrays
8731
     * @param {number} [start=0] The start of the range.
8732
     * @param {number} end The end of the range.
8733
     * @param {number} [step=1] The value to increment or decrement by.
8734
     * @returns {Array} Returns a new range array.
8735
     * @example
8736
     *
8737
     * _.range(4);
8738
     * // => [0, 1, 2, 3]
8739
     *
8740
     * _.range(1, 5);
8741
     * // => [1, 2, 3, 4]
8742
     *
8743
     * _.range(0, 20, 5);
8744
     * // => [0, 5, 10, 15]
8745
     *
8746
     * _.range(0, -4, -1);
8747
     * // => [0, -1, -2, -3]
8748
     *
8749
     * _.range(1, 4, 0);
8750
     * // => [1, 1, 1]
8751
     *
8752
     * _.range(0);
8753
     * // => []
8754
     */
8755
    function range(start, end, step) {
8756
      start = +start || 0;
8757
      step = typeof step == 'number' ? step : (+step || 1);
8758

    
8759
      if (end == null) {
8760
        end = start;
8761
        start = 0;
8762
      }
8763
      // use `Array(length)` so engines like Chakra and V8 avoid slower modes
8764
      // http://youtu.be/XAqIpGU8ZZk#t=17m25s
8765
      var index = -1,
8766
          length = nativeMax(0, ceil((end - start) / (step || 1))),
8767
          result = Array(length);
8768

    
8769
      while (++index < length) {
8770
        result[index] = start;
8771
        start += step;
8772
      }
8773
      return result;
8774
    }
8775

    
8776
    /**
8777
     * Removes all elements from an array that the callback returns truey for
8778
     * and returns an array of removed elements. The callback is bound to `thisArg`
8779
     * and invoked with three arguments; (value, index, array).
8780
     *
8781
     * If a property name is provided for `callback` the created "_.pluck" style
8782
     * callback will return the property value of the given element.
8783
     *
8784
     * If an object is provided for `callback` the created "_.where" style callback
8785
     * will return `true` for elements that have the properties of the given object,
8786
     * else `false`.
8787
     *
8788
     * @static
8789
     * @memberOf _
8790
     * @category Arrays
8791
     * @param {Array} array The array to modify.
8792
     * @param {Function|Object|string} [callback=identity] The function called
8793
     *  per iteration. If a property name or object is provided it will be used
8794
     *  to create a "_.pluck" or "_.where" style callback, respectively.
8795
     * @param {*} [thisArg] The `this` binding of `callback`.
8796
     * @returns {Array} Returns a new array of removed elements.
8797
     * @example
8798
     *
8799
     * var array = [1, 2, 3, 4, 5, 6];
8800
     * var evens = _.remove(array, function(num) { return num % 2 == 0; });
8801
     *
8802
     * console.log(array);
8803
     * // => [1, 3, 5]
8804
     *
8805
     * console.log(evens);
8806
     * // => [2, 4, 6]
8807
     */
8808
    function remove(array, callback, thisArg) {
8809
      var index = -1,
8810
          length = array ? array.length : 0,
8811
          result = [];
8812

    
8813
      callback = lodash.createCallback(callback, thisArg, 3);
8814
      while (++index < length) {
8815
        var value = array[index];
8816
        if (callback(value, index, array)) {
8817
          result.push(value);
8818
          splice.call(array, index--, 1);
8819
          length--;
8820
        }
8821
      }
8822
      return result;
8823
    }
8824

    
8825
    /**
8826
     * The opposite of `_.initial` this method gets all but the first element or
8827
     * first `n` elements of an array. If a callback function is provided elements
8828
     * at the beginning of the array are excluded from the result as long as the
8829
     * callback returns truey. The callback is bound to `thisArg` and invoked
8830
     * with three arguments; (value, index, array).
8831
     *
8832
     * If a property name is provided for `callback` the created "_.pluck" style
8833
     * callback will return the property value of the given element.
8834
     *
8835
     * If an object is provided for `callback` the created "_.where" style callback
8836
     * will return `true` for elements that have the properties of the given object,
8837
     * else `false`.
8838
     *
8839
     * @static
8840
     * @memberOf _
8841
     * @alias drop, tail
8842
     * @category Arrays
8843
     * @param {Array} array The array to query.
8844
     * @param {Function|Object|number|string} [callback=1] The function called
8845
     *  per element or the number of elements to exclude. If a property name or
8846
     *  object is provided it will be used to create a "_.pluck" or "_.where"
8847
     *  style callback, respectively.
8848
     * @param {*} [thisArg] The `this` binding of `callback`.
8849
     * @returns {Array} Returns a slice of `array`.
8850
     * @example
8851
     *
8852
     * _.rest([1, 2, 3]);
8853
     * // => [2, 3]
8854
     *
8855
     * _.rest([1, 2, 3], 2);
8856
     * // => [3]
8857
     *
8858
     * _.rest([1, 2, 3], function(num) {
8859
     *   return num < 3;
8860
     * });
8861
     * // => [3]
8862
     *
8863
     * var characters = [
8864
     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
8865
     *   { 'name': 'fred',    'blocked': false,  'employer': 'slate' },
8866
     *   { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
8867
     * ];
8868
     *
8869
     * // using "_.pluck" callback shorthand
8870
     * _.pluck(_.rest(characters, 'blocked'), 'name');
8871
     * // => ['fred', 'pebbles']
8872
     *
8873
     * // using "_.where" callback shorthand
8874
     * _.rest(characters, { 'employer': 'slate' });
8875
     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
8876
     */
8877
    function rest(array, callback, thisArg) {
8878
      if (typeof callback != 'number' && callback != null) {
8879
        var n = 0,
8880
            index = -1,
8881
            length = array ? array.length : 0;
8882

    
8883
        callback = lodash.createCallback(callback, thisArg, 3);
8884
        while (++index < length && callback(array[index], index, array)) {
8885
          n++;
8886
        }
8887
      } else {
8888
        n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
8889
      }
8890
      return slice(array, n);
8891
    }
8892

    
8893
    /**
8894
     * Uses a binary search to determine the smallest index at which a value
8895
     * should be inserted into a given sorted array in order to maintain the sort
8896
     * order of the array. If a callback is provided it will be executed for
8897
     * `value` and each element of `array` to compute their sort ranking. The
8898
     * callback is bound to `thisArg` and invoked with one argument; (value).
8899
     *
8900
     * If a property name is provided for `callback` the created "_.pluck" style
8901
     * callback will return the property value of the given element.
8902
     *
8903
     * If an object is provided for `callback` the created "_.where" style callback
8904
     * will return `true` for elements that have the properties of the given object,
8905
     * else `false`.
8906
     *
8907
     * @static
8908
     * @memberOf _
8909
     * @category Arrays
8910
     * @param {Array} array The array to inspect.
8911
     * @param {*} value The value to evaluate.
8912
     * @param {Function|Object|string} [callback=identity] The function called
8913
     *  per iteration. If a property name or object is provided it will be used
8914
     *  to create a "_.pluck" or "_.where" style callback, respectively.
8915
     * @param {*} [thisArg] The `this` binding of `callback`.
8916
     * @returns {number} Returns the index at which `value` should be inserted
8917
     *  into `array`.
8918
     * @example
8919
     *
8920
     * _.sortedIndex([20, 30, 50], 40);
8921
     * // => 2
8922
     *
8923
     * // using "_.pluck" callback shorthand
8924
     * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
8925
     * // => 2
8926
     *
8927
     * var dict = {
8928
     *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
8929
     * };
8930
     *
8931
     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
8932
     *   return dict.wordToNumber[word];
8933
     * });
8934
     * // => 2
8935
     *
8936
     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
8937
     *   return this.wordToNumber[word];
8938
     * }, dict);
8939
     * // => 2
8940
     */
8941
    function sortedIndex(array, value, callback, thisArg) {
8942
      var low = 0,
8943
          high = array ? array.length : low;
8944

    
8945
      // explicitly reference `identity` for better inlining in Firefox
8946
      callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
8947
      value = callback(value);
8948

    
8949
      while (low < high) {
8950
        var mid = (low + high) >>> 1;
8951
        (callback(array[mid]) < value)
8952
          ? low = mid + 1
8953
          : high = mid;
8954
      }
8955
      return low;
8956
    }
8957

    
8958
    /**
8959
     * Creates an array of unique values, in order, of the provided arrays using
8960
     * strict equality for comparisons, i.e. `===`.
8961
     *
8962
     * @static
8963
     * @memberOf _
8964
     * @category Arrays
8965
     * @param {...Array} [array] The arrays to inspect.
8966
     * @returns {Array} Returns an array of combined values.
8967
     * @example
8968
     *
8969
     * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
8970
     * // => [1, 2, 3, 5, 4]
8971
     */
8972
    function union() {
8973
      return baseUniq(baseFlatten(arguments, true, true));
8974
    }
8975

    
8976
    /**
8977
     * Creates a duplicate-value-free version of an array using strict equality
8978
     * for comparisons, i.e. `===`. If the array is sorted, providing
8979
     * `true` for `isSorted` will use a faster algorithm. If a callback is provided
8980
     * each element of `array` is passed through the callback before uniqueness
8981
     * is computed. The callback is bound to `thisArg` and invoked with three
8982
     * arguments; (value, index, array).
8983
     *
8984
     * If a property name is provided for `callback` the created "_.pluck" style
8985
     * callback will return the property value of the given element.
8986
     *
8987
     * If an object is provided for `callback` the created "_.where" style callback
8988
     * will return `true` for elements that have the properties of the given object,
8989
     * else `false`.
8990
     *
8991
     * @static
8992
     * @memberOf _
8993
     * @alias unique
8994
     * @category Arrays
8995
     * @param {Array} array The array to process.
8996
     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
8997
     * @param {Function|Object|string} [callback=identity] The function called
8998
     *  per iteration. If a property name or object is provided it will be used
8999
     *  to create a "_.pluck" or "_.where" style callback, respectively.
9000
     * @param {*} [thisArg] The `this` binding of `callback`.
9001
     * @returns {Array} Returns a duplicate-value-free array.
9002
     * @example
9003
     *
9004
     * _.uniq([1, 2, 1, 3, 1]);
9005
     * // => [1, 2, 3]
9006
     *
9007
     * _.uniq([1, 1, 2, 2, 3], true);
9008
     * // => [1, 2, 3]
9009
     *
9010
     * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
9011
     * // => ['A', 'b', 'C']
9012
     *
9013
     * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
9014
     * // => [1, 2.5, 3]
9015
     *
9016
     * // using "_.pluck" callback shorthand
9017
     * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
9018
     * // => [{ 'x': 1 }, { 'x': 2 }]
9019
     */
9020
    function uniq(array, isSorted, callback, thisArg) {
9021
      // juggle arguments
9022
      if (typeof isSorted != 'boolean' && isSorted != null) {
9023
        thisArg = callback;
9024
        callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
9025
        isSorted = false;
9026
      }
9027
      if (callback != null) {
9028
        callback = lodash.createCallback(callback, thisArg, 3);
9029
      }
9030
      return baseUniq(array, isSorted, callback);
9031
    }
9032

    
9033
    /**
9034
     * Creates an array excluding all provided values using strict equality for
9035
     * comparisons, i.e. `===`.
9036
     *
9037
     * @static
9038
     * @memberOf _
9039
     * @category Arrays
9040
     * @param {Array} array The array to filter.
9041
     * @param {...*} [value] The values to exclude.
9042
     * @returns {Array} Returns a new array of filtered values.
9043
     * @example
9044
     *
9045
     * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
9046
     * // => [2, 3, 4]
9047
     */
9048
    function without(array) {
9049
      return baseDifference(array, slice(arguments, 1));
9050
    }
9051

    
9052
    /**
9053
     * Creates an array that is the symmetric difference of the provided arrays.
9054
     * See http://en.wikipedia.org/wiki/Symmetric_difference.
9055
     *
9056
     * @static
9057
     * @memberOf _
9058
     * @category Arrays
9059
     * @param {...Array} [array] The arrays to inspect.
9060
     * @returns {Array} Returns an array of values.
9061
     * @example
9062
     *
9063
     * _.xor([1, 2, 3], [5, 2, 1, 4]);
9064
     * // => [3, 5, 4]
9065
     *
9066
     * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
9067
     * // => [1, 4, 5]
9068
     */
9069
    function xor() {
9070
      var index = -1,
9071
          length = arguments.length;
9072

    
9073
      while (++index < length) {
9074
        var array = arguments[index];
9075
        if (isArray(array) || isArguments(array)) {
9076
          var result = result
9077
            ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
9078
            : array;
9079
        }
9080
      }
9081
      return result || [];
9082
    }
9083

    
9084
    /**
9085
     * Creates an array of grouped elements, the first of which contains the first
9086
     * elements of the given arrays, the second of which contains the second
9087
     * elements of the given arrays, and so on.
9088
     *
9089
     * @static
9090
     * @memberOf _
9091
     * @alias unzip
9092
     * @category Arrays
9093
     * @param {...Array} [array] Arrays to process.
9094
     * @returns {Array} Returns a new array of grouped elements.
9095
     * @example
9096
     *
9097
     * _.zip(['fred', 'barney'], [30, 40], [true, false]);
9098
     * // => [['fred', 30, true], ['barney', 40, false]]
9099
     */
9100
    function zip() {
9101
      var array = arguments.length > 1 ? arguments : arguments[0],
9102
          index = -1,
9103
          length = array ? max(pluck(array, 'length')) : 0,
9104
          result = Array(length < 0 ? 0 : length);
9105

    
9106
      while (++index < length) {
9107
        result[index] = pluck(array, index);
9108
      }
9109
      return result;
9110
    }
9111

    
9112
    /**
9113
     * Creates an object composed from arrays of `keys` and `values`. Provide
9114
     * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
9115
     * or two arrays, one of `keys` and one of corresponding `values`.
9116
     *
9117
     * @static
9118
     * @memberOf _
9119
     * @alias object
9120
     * @category Arrays
9121
     * @param {Array} keys The array of keys.
9122
     * @param {Array} [values=[]] The array of values.
9123
     * @returns {Object} Returns an object composed of the given keys and
9124
     *  corresponding values.
9125
     * @example
9126
     *
9127
     * _.zipObject(['fred', 'barney'], [30, 40]);
9128
     * // => { 'fred': 30, 'barney': 40 }
9129
     */
9130
    function zipObject(keys, values) {
9131
      var index = -1,
9132
          length = keys ? keys.length : 0,
9133
          result = {};
9134

    
9135
      if (!values && length && !isArray(keys[0])) {
9136
        values = [];
9137
      }
9138
      while (++index < length) {
9139
        var key = keys[index];
9140
        if (values) {
9141
          result[key] = values[index];
9142
        } else if (key) {
9143
          result[key[0]] = key[1];
9144
        }
9145
      }
9146
      return result;
9147
    }
9148

    
9149
    /*--------------------------------------------------------------------------*/
9150

    
9151
    /**
9152
     * Creates a function that executes `func`, with  the `this` binding and
9153
     * arguments of the created function, only after being called `n` times.
9154
     *
9155
     * @static
9156
     * @memberOf _
9157
     * @category Functions
9158
     * @param {number} n The number of times the function must be called before
9159
     *  `func` is executed.
9160
     * @param {Function} func The function to restrict.
9161
     * @returns {Function} Returns the new restricted function.
9162
     * @example
9163
     *
9164
     * var saves = ['profile', 'settings'];
9165
     *
9166
     * var done = _.after(saves.length, function() {
9167
     *   console.log('Done saving!');
9168
     * });
9169
     *
9170
     * _.forEach(saves, function(type) {
9171
     *   asyncSave({ 'type': type, 'complete': done });
9172
     * });
9173
     * // => logs 'Done saving!', after all saves have completed
9174
     */
9175
    function after(n, func) {
9176
      if (!isFunction(func)) {
9177
        throw new TypeError;
9178
      }
9179
      return function() {
9180
        if (--n < 1) {
9181
          return func.apply(this, arguments);
9182
        }
9183
      };
9184
    }
9185

    
9186
    /**
9187
     * Creates a function that, when called, invokes `func` with the `this`
9188
     * binding of `thisArg` and prepends any additional `bind` arguments to those
9189
     * provided to the bound function.
9190
     *
9191
     * @static
9192
     * @memberOf _
9193
     * @category Functions
9194
     * @param {Function} func The function to bind.
9195
     * @param {*} [thisArg] The `this` binding of `func`.
9196
     * @param {...*} [arg] Arguments to be partially applied.
9197
     * @returns {Function} Returns the new bound function.
9198
     * @example
9199
     *
9200
     * var func = function(greeting) {
9201
     *   return greeting + ' ' + this.name;
9202
     * };
9203
     *
9204
     * func = _.bind(func, { 'name': 'fred' }, 'hi');
9205
     * func();
9206
     * // => 'hi fred'
9207
     */
9208
    function bind(func, thisArg) {
9209
      return arguments.length > 2
9210
        ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
9211
        : createWrapper(func, 1, null, null, thisArg);
9212
    }
9213

    
9214
    /**
9215
     * Binds methods of an object to the object itself, overwriting the existing
9216
     * method. Method names may be specified as individual arguments or as arrays
9217
     * of method names. If no method names are provided all the function properties
9218
     * of `object` will be bound.
9219
     *
9220
     * @static
9221
     * @memberOf _
9222
     * @category Functions
9223
     * @param {Object} object The object to bind and assign the bound methods to.
9224
     * @param {...string} [methodName] The object method names to
9225
     *  bind, specified as individual method names or arrays of method names.
9226
     * @returns {Object} Returns `object`.
9227
     * @example
9228
     *
9229
     * var view = {
9230
     *   'label': 'docs',
9231
     *   'onClick': function() { console.log('clicked ' + this.label); }
9232
     * };
9233
     *
9234
     * _.bindAll(view);
9235
     * jQuery('#docs').on('click', view.onClick);
9236
     * // => logs 'clicked docs', when the button is clicked
9237
     */
9238
    function bindAll(object) {
9239
      var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
9240
          index = -1,
9241
          length = funcs.length;
9242

    
9243
      while (++index < length) {
9244
        var key = funcs[index];
9245
        object[key] = createWrapper(object[key], 1, null, null, object);
9246
      }
9247
      return object;
9248
    }
9249

    
9250
    /**
9251
     * Creates a function that, when called, invokes the method at `object[key]`
9252
     * and prepends any additional `bindKey` arguments to those provided to the bound
9253
     * function. This method differs from `_.bind` by allowing bound functions to
9254
     * reference methods that will be redefined or don't yet exist.
9255
     * See http://michaux.ca/articles/lazy-function-definition-pattern.
9256
     *
9257
     * @static
9258
     * @memberOf _
9259
     * @category Functions
9260
     * @param {Object} object The object the method belongs to.
9261
     * @param {string} key The key of the method.
9262
     * @param {...*} [arg] Arguments to be partially applied.
9263
     * @returns {Function} Returns the new bound function.
9264
     * @example
9265
     *
9266
     * var object = {
9267
     *   'name': 'fred',
9268
     *   'greet': function(greeting) {
9269
     *     return greeting + ' ' + this.name;
9270
     *   }
9271
     * };
9272
     *
9273
     * var func = _.bindKey(object, 'greet', 'hi');
9274
     * func();
9275
     * // => 'hi fred'
9276
     *
9277
     * object.greet = function(greeting) {
9278
     *   return greeting + 'ya ' + this.name + '!';
9279
     * };
9280
     *
9281
     * func();
9282
     * // => 'hiya fred!'
9283
     */
9284
    function bindKey(object, key) {
9285
      return arguments.length > 2
9286
        ? createWrapper(key, 19, slice(arguments, 2), null, object)
9287
        : createWrapper(key, 3, null, null, object);
9288
    }
9289

    
9290
    /**
9291
     * Creates a function that is the composition of the provided functions,
9292
     * where each function consumes the return value of the function that follows.
9293
     * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
9294
     * Each function is executed with the `this` binding of the composed function.
9295
     *
9296
     * @static
9297
     * @memberOf _
9298
     * @category Functions
9299
     * @param {...Function} [func] Functions to compose.
9300
     * @returns {Function} Returns the new composed function.
9301
     * @example
9302
     *
9303
     * var realNameMap = {
9304
     *   'pebbles': 'penelope'
9305
     * };
9306
     *
9307
     * var format = function(name) {
9308
     *   name = realNameMap[name.toLowerCase()] || name;
9309
     *   return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
9310
     * };
9311
     *
9312
     * var greet = function(formatted) {
9313
     *   return 'Hiya ' + formatted + '!';
9314
     * };
9315
     *
9316
     * var welcome = _.compose(greet, format);
9317
     * welcome('pebbles');
9318
     * // => 'Hiya Penelope!'
9319
     */
9320
    function compose() {
9321
      var funcs = arguments,
9322
          length = funcs.length;
9323

    
9324
      while (length--) {
9325
        if (!isFunction(funcs[length])) {
9326
          throw new TypeError;
9327
        }
9328
      }
9329
      return function() {
9330
        var args = arguments,
9331
            length = funcs.length;
9332

    
9333
        while (length--) {
9334
          args = [funcs[length].apply(this, args)];
9335
        }
9336
        return args[0];
9337
      };
9338
    }
9339

    
9340
    /**
9341
     * Creates a function which accepts one or more arguments of `func` that when
9342
     * invoked either executes `func` returning its result, if all `func` arguments
9343
     * have been provided, or returns a function that accepts one or more of the
9344
     * remaining `func` arguments, and so on. The arity of `func` can be specified
9345
     * if `func.length` is not sufficient.
9346
     *
9347
     * @static
9348
     * @memberOf _
9349
     * @category Functions
9350
     * @param {Function} func The function to curry.
9351
     * @param {number} [arity=func.length] The arity of `func`.
9352
     * @returns {Function} Returns the new curried function.
9353
     * @example
9354
     *
9355
     * var curried = _.curry(function(a, b, c) {
9356
     *   console.log(a + b + c);
9357
     * });
9358
     *
9359
     * curried(1)(2)(3);
9360
     * // => 6
9361
     *
9362
     * curried(1, 2)(3);
9363
     * // => 6
9364
     *
9365
     * curried(1, 2, 3);
9366
     * // => 6
9367
     */
9368
    function curry(func, arity) {
9369
      arity = typeof arity == 'number' ? arity : (+arity || func.length);
9370
      return createWrapper(func, 4, null, null, null, arity);
9371
    }
9372

    
9373
    /**
9374
     * Creates a function that will delay the execution of `func` until after
9375
     * `wait` milliseconds have elapsed since the last time it was invoked.
9376
     * Provide an options object to indicate that `func` should be invoked on
9377
     * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
9378
     * to the debounced function will return the result of the last `func` call.
9379
     *
9380
     * Note: If `leading` and `trailing` options are `true` `func` will be called
9381
     * on the trailing edge of the timeout only if the the debounced function is
9382
     * invoked more than once during the `wait` timeout.
9383
     *
9384
     * @static
9385
     * @memberOf _
9386
     * @category Functions
9387
     * @param {Function} func The function to debounce.
9388
     * @param {number} wait The number of milliseconds to delay.
9389
     * @param {Object} [options] The options object.
9390
     * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
9391
     * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
9392
     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
9393
     * @returns {Function} Returns the new debounced function.
9394
     * @example
9395
     *
9396
     * // avoid costly calculations while the window size is in flux
9397
     * var lazyLayout = _.debounce(calculateLayout, 150);
9398
     * jQuery(window).on('resize', lazyLayout);
9399
     *
9400
     * // execute `sendMail` when the click event is fired, debouncing subsequent calls
9401
     * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
9402
     *   'leading': true,
9403
     *   'trailing': false
9404
     * });
9405
     *
9406
     * // ensure `batchLog` is executed once after 1 second of debounced calls
9407
     * var source = new EventSource('/stream');
9408
     * source.addEventListener('message', _.debounce(batchLog, 250, {
9409
     *   'maxWait': 1000
9410
     * }, false);
9411
     */
9412
    function debounce(func, wait, options) {
9413
      var args,
9414
          maxTimeoutId,
9415
          result,
9416
          stamp,
9417
          thisArg,
9418
          timeoutId,
9419
          trailingCall,
9420
          lastCalled = 0,
9421
          maxWait = false,
9422
          trailing = true;
9423

    
9424
      if (!isFunction(func)) {
9425
        throw new TypeError;
9426
      }
9427
      wait = nativeMax(0, wait) || 0;
9428
      if (options === true) {
9429
        var leading = true;
9430
        trailing = false;
9431
      } else if (isObject(options)) {
9432
        leading = options.leading;
9433
        maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
9434
        trailing = 'trailing' in options ? options.trailing : trailing;
9435
      }
9436
      var delayed = function() {
9437
        var remaining = wait - (now() - stamp);
9438
        if (remaining <= 0) {
9439
          if (maxTimeoutId) {
9440
            clearTimeout(maxTimeoutId);
9441
          }
9442
          var isCalled = trailingCall;
9443
          maxTimeoutId = timeoutId = trailingCall = undefined;
9444
          if (isCalled) {
9445
            lastCalled = now();
9446
            result = func.apply(thisArg, args);
9447
            if (!timeoutId && !maxTimeoutId) {
9448
              args = thisArg = null;
9449
            }
9450
          }
9451
        } else {
9452
          timeoutId = setTimeout(delayed, remaining);
9453
        }
9454
      };
9455

    
9456
      var maxDelayed = function() {
9457
        if (timeoutId) {
9458
          clearTimeout(timeoutId);
9459
        }
9460
        maxTimeoutId = timeoutId = trailingCall = undefined;
9461
        if (trailing || (maxWait !== wait)) {
9462
          lastCalled = now();
9463
          result = func.apply(thisArg, args);
9464
          if (!timeoutId && !maxTimeoutId) {
9465
            args = thisArg = null;
9466
          }
9467
        }
9468
      };
9469

    
9470
      return function() {
9471
        args = arguments;
9472
        stamp = now();
9473
        thisArg = this;
9474
        trailingCall = trailing && (timeoutId || !leading);
9475

    
9476
        if (maxWait === false) {
9477
          var leadingCall = leading && !timeoutId;
9478
        } else {
9479
          if (!maxTimeoutId && !leading) {
9480
            lastCalled = stamp;
9481
          }
9482
          var remaining = maxWait - (stamp - lastCalled),
9483
              isCalled = remaining <= 0;
9484

    
9485
          if (isCalled) {
9486
            if (maxTimeoutId) {
9487
              maxTimeoutId = clearTimeout(maxTimeoutId);
9488
            }
9489
            lastCalled = stamp;
9490
            result = func.apply(thisArg, args);
9491
          }
9492
          else if (!maxTimeoutId) {
9493
            maxTimeoutId = setTimeout(maxDelayed, remaining);
9494
          }
9495
        }
9496
        if (isCalled && timeoutId) {
9497
          timeoutId = clearTimeout(timeoutId);
9498
        }
9499
        else if (!timeoutId && wait !== maxWait) {
9500
          timeoutId = setTimeout(delayed, wait);
9501
        }
9502
        if (leadingCall) {
9503
          isCalled = true;
9504
          result = func.apply(thisArg, args);
9505
        }
9506
        if (isCalled && !timeoutId && !maxTimeoutId) {
9507
          args = thisArg = null;
9508
        }
9509
        return result;
9510
      };
9511
    }
9512

    
9513
    /**
9514
     * Defers executing the `func` function until the current call stack has cleared.
9515
     * Additional arguments will be provided to `func` when it is invoked.
9516
     *
9517
     * @static
9518
     * @memberOf _
9519
     * @category Functions
9520
     * @param {Function} func The function to defer.
9521
     * @param {...*} [arg] Arguments to invoke the function with.
9522
     * @returns {number} Returns the timer id.
9523
     * @example
9524
     *
9525
     * _.defer(function(text) { console.log(text); }, 'deferred');
9526
     * // logs 'deferred' after one or more milliseconds
9527
     */
9528
    function defer(func) {
9529
      if (!isFunction(func)) {
9530
        throw new TypeError;
9531
      }
9532
      var args = slice(arguments, 1);
9533
      return setTimeout(function() { func.apply(undefined, args); }, 1);
9534
    }
9535

    
9536
    /**
9537
     * Executes the `func` function after `wait` milliseconds. Additional arguments
9538
     * will be provided to `func` when it is invoked.
9539
     *
9540
     * @static
9541
     * @memberOf _
9542
     * @category Functions
9543
     * @param {Function} func The function to delay.
9544
     * @param {number} wait The number of milliseconds to delay execution.
9545
     * @param {...*} [arg] Arguments to invoke the function with.
9546
     * @returns {number} Returns the timer id.
9547
     * @example
9548
     *
9549
     * _.delay(function(text) { console.log(text); }, 1000, 'later');
9550
     * // => logs 'later' after one second
9551
     */
9552
    function delay(func, wait) {
9553
      if (!isFunction(func)) {
9554
        throw new TypeError;
9555
      }
9556
      var args = slice(arguments, 2);
9557
      return setTimeout(function() { func.apply(undefined, args); }, wait);
9558
    }
9559

    
9560
    /**
9561
     * Creates a function that memoizes the result of `func`. If `resolver` is
9562
     * provided it will be used to determine the cache key for storing the result
9563
     * based on the arguments provided to the memoized function. By default, the
9564
     * first argument provided to the memoized function is used as the cache key.
9565
     * The `func` is executed with the `this` binding of the memoized function.
9566
     * The result cache is exposed as the `cache` property on the memoized function.
9567
     *
9568
     * @static
9569
     * @memberOf _
9570
     * @category Functions
9571
     * @param {Function} func The function to have its output memoized.
9572
     * @param {Function} [resolver] A function used to resolve the cache key.
9573
     * @returns {Function} Returns the new memoizing function.
9574
     * @example
9575
     *
9576
     * var fibonacci = _.memoize(function(n) {
9577
     *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
9578
     * });
9579
     *
9580
     * fibonacci(9)
9581
     * // => 34
9582
     *
9583
     * var data = {
9584
     *   'fred': { 'name': 'fred', 'age': 40 },
9585
     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
9586
     * };
9587
     *
9588
     * // modifying the result cache
9589
     * var get = _.memoize(function(name) { return data[name]; }, _.identity);
9590
     * get('pebbles');
9591
     * // => { 'name': 'pebbles', 'age': 1 }
9592
     *
9593
     * get.cache.pebbles.name = 'penelope';
9594
     * get('pebbles');
9595
     * // => { 'name': 'penelope', 'age': 1 }
9596
     */
9597
    function memoize(func, resolver) {
9598
      if (!isFunction(func)) {
9599
        throw new TypeError;
9600
      }
9601
      var memoized = function() {
9602
        var cache = memoized.cache,
9603
            key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
9604

    
9605
        return hasOwnProperty.call(cache, key)
9606
          ? cache[key]
9607
          : (cache[key] = func.apply(this, arguments));
9608
      }
9609
      memoized.cache = {};
9610
      return memoized;
9611
    }
9612

    
9613
    /**
9614
     * Creates a function that is restricted to execute `func` once. Repeat calls to
9615
     * the function will return the value of the first call. The `func` is executed
9616
     * with the `this` binding of the created function.
9617
     *
9618
     * @static
9619
     * @memberOf _
9620
     * @category Functions
9621
     * @param {Function} func The function to restrict.
9622
     * @returns {Function} Returns the new restricted function.
9623
     * @example
9624
     *
9625
     * var initialize = _.once(createApplication);
9626
     * initialize();
9627
     * initialize();
9628
     * // `initialize` executes `createApplication` once
9629
     */
9630
    function once(func) {
9631
      var ran,
9632
          result;
9633

    
9634
      if (!isFunction(func)) {
9635
        throw new TypeError;
9636
      }
9637
      return function() {
9638
        if (ran) {
9639
          return result;
9640
        }
9641
        ran = true;
9642
        result = func.apply(this, arguments);
9643

    
9644
        // clear the `func` variable so the function may be garbage collected
9645
        func = null;
9646
        return result;
9647
      };
9648
    }
9649

    
9650
    /**
9651
     * Creates a function that, when called, invokes `func` with any additional
9652
     * `partial` arguments prepended to those provided to the new function. This
9653
     * method is similar to `_.bind` except it does **not** alter the `this` binding.
9654
     *
9655
     * @static
9656
     * @memberOf _
9657
     * @category Functions
9658
     * @param {Function} func The function to partially apply arguments to.
9659
     * @param {...*} [arg] Arguments to be partially applied.
9660
     * @returns {Function} Returns the new partially applied function.
9661
     * @example
9662
     *
9663
     * var greet = function(greeting, name) { return greeting + ' ' + name; };
9664
     * var hi = _.partial(greet, 'hi');
9665
     * hi('fred');
9666
     * // => 'hi fred'
9667
     */
9668
    function partial(func) {
9669
      return createWrapper(func, 16, slice(arguments, 1));
9670
    }
9671

    
9672
    /**
9673
     * This method is like `_.partial` except that `partial` arguments are
9674
     * appended to those provided to the new function.
9675
     *
9676
     * @static
9677
     * @memberOf _
9678
     * @category Functions
9679
     * @param {Function} func The function to partially apply arguments to.
9680
     * @param {...*} [arg] Arguments to be partially applied.
9681
     * @returns {Function} Returns the new partially applied function.
9682
     * @example
9683
     *
9684
     * var defaultsDeep = _.partialRight(_.merge, _.defaults);
9685
     *
9686
     * var options = {
9687
     *   'variable': 'data',
9688
     *   'imports': { 'jq': $ }
9689
     * };
9690
     *
9691
     * defaultsDeep(options, _.templateSettings);
9692
     *
9693
     * options.variable
9694
     * // => 'data'
9695
     *
9696
     * options.imports
9697
     * // => { '_': _, 'jq': $ }
9698
     */
9699
    function partialRight(func) {
9700
      return createWrapper(func, 32, null, slice(arguments, 1));
9701
    }
9702

    
9703
    /**
9704
     * Creates a function that, when executed, will only call the `func` function
9705
     * at most once per every `wait` milliseconds. Provide an options object to
9706
     * indicate that `func` should be invoked on the leading and/or trailing edge
9707
     * of the `wait` timeout. Subsequent calls to the throttled function will
9708
     * return the result of the last `func` call.
9709
     *
9710
     * Note: If `leading` and `trailing` options are `true` `func` will be called
9711
     * on the trailing edge of the timeout only if the the throttled function is
9712
     * invoked more than once during the `wait` timeout.
9713
     *
9714
     * @static
9715
     * @memberOf _
9716
     * @category Functions
9717
     * @param {Function} func The function to throttle.
9718
     * @param {number} wait The number of milliseconds to throttle executions to.
9719
     * @param {Object} [options] The options object.
9720
     * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
9721
     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
9722
     * @returns {Function} Returns the new throttled function.
9723
     * @example
9724
     *
9725
     * // avoid excessively updating the position while scrolling
9726
     * var throttled = _.throttle(updatePosition, 100);
9727
     * jQuery(window).on('scroll', throttled);
9728
     *
9729
     * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
9730
     * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
9731
     *   'trailing': false
9732
     * }));
9733
     */
9734
    function throttle(func, wait, options) {
9735
      var leading = true,
9736
          trailing = true;
9737

    
9738
      if (!isFunction(func)) {
9739
        throw new TypeError;
9740
      }
9741
      if (options === false) {
9742
        leading = false;
9743
      } else if (isObject(options)) {
9744
        leading = 'leading' in options ? options.leading : leading;
9745
        trailing = 'trailing' in options ? options.trailing : trailing;
9746
      }
9747
      debounceOptions.leading = leading;
9748
      debounceOptions.maxWait = wait;
9749
      debounceOptions.trailing = trailing;
9750

    
9751
      return debounce(func, wait, debounceOptions);
9752
    }
9753

    
9754
    /**
9755
     * Creates a function that provides `value` to the wrapper function as its
9756
     * first argument. Additional arguments provided to the function are appended
9757
     * to those provided to the wrapper function. The wrapper is executed with
9758
     * the `this` binding of the created function.
9759
     *
9760
     * @static
9761
     * @memberOf _
9762
     * @category Functions
9763
     * @param {*} value The value to wrap.
9764
     * @param {Function} wrapper The wrapper function.
9765
     * @returns {Function} Returns the new function.
9766
     * @example
9767
     *
9768
     * var p = _.wrap(_.escape, function(func, text) {
9769
     *   return '<p>' + func(text) + '</p>';
9770
     * });
9771
     *
9772
     * p('Fred, Wilma, & Pebbles');
9773
     * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
9774
     */
9775
    function wrap(value, wrapper) {
9776
      return createWrapper(wrapper, 16, [value]);
9777
    }
9778

    
9779
    /*--------------------------------------------------------------------------*/
9780

    
9781
    /**
9782
     * Creates a function that returns `value`.
9783
     *
9784
     * @static
9785
     * @memberOf _
9786
     * @category Utilities
9787
     * @param {*} value The value to return from the new function.
9788
     * @returns {Function} Returns the new function.
9789
     * @example
9790
     *
9791
     * var object = { 'name': 'fred' };
9792
     * var getter = _.constant(object);
9793
     * getter() === object;
9794
     * // => true
9795
     */
9796
    function constant(value) {
9797
      return function() {
9798
        return value;
9799
      };
9800
    }
9801

    
9802
    /**
9803
     * Produces a callback bound to an optional `thisArg`. If `func` is a property
9804
     * name the created callback will return the property value for a given element.
9805
     * If `func` is an object the created callback will return `true` for elements
9806
     * that contain the equivalent object properties, otherwise it will return `false`.
9807
     *
9808
     * @static
9809
     * @memberOf _
9810
     * @category Utilities
9811
     * @param {*} [func=identity] The value to convert to a callback.
9812
     * @param {*} [thisArg] The `this` binding of the created callback.
9813
     * @param {number} [argCount] The number of arguments the callback accepts.
9814
     * @returns {Function} Returns a callback function.
9815
     * @example
9816
     *
9817
     * var characters = [
9818
     *   { 'name': 'barney', 'age': 36 },
9819
     *   { 'name': 'fred',   'age': 40 }
9820
     * ];
9821
     *
9822
     * // wrap to create custom callback shorthands
9823
     * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
9824
     *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
9825
     *   return !match ? func(callback, thisArg) : function(object) {
9826
     *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
9827
     *   };
9828
     * });
9829
     *
9830
     * _.filter(characters, 'age__gt38');
9831
     * // => [{ 'name': 'fred', 'age': 40 }]
9832
     */
9833
    function createCallback(func, thisArg, argCount) {
9834
      var type = typeof func;
9835
      if (func == null || type == 'function') {
9836
        return baseCreateCallback(func, thisArg, argCount);
9837
      }
9838
      // handle "_.pluck" style callback shorthands
9839
      if (type != 'object') {
9840
        return property(func);
9841
      }
9842
      var props = keys(func),
9843
          key = props[0],
9844
          a = func[key];
9845

    
9846
      // handle "_.where" style callback shorthands
9847
      if (props.length == 1 && a === a && !isObject(a)) {
9848
        // fast path the common case of providing an object with a single
9849
        // property containing a primitive value
9850
        return function(object) {
9851
          var b = object[key];
9852
          return a === b && (a !== 0 || (1 / a == 1 / b));
9853
        };
9854
      }
9855
      return function(object) {
9856
        var length = props.length,
9857
            result = false;
9858

    
9859
        while (length--) {
9860
          if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
9861
            break;
9862
          }
9863
        }
9864
        return result;
9865
      };
9866
    }
9867

    
9868
    /**
9869
     * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
9870
     * corresponding HTML entities.
9871
     *
9872
     * @static
9873
     * @memberOf _
9874
     * @category Utilities
9875
     * @param {string} string The string to escape.
9876
     * @returns {string} Returns the escaped string.
9877
     * @example
9878
     *
9879
     * _.escape('Fred, Wilma, & Pebbles');
9880
     * // => 'Fred, Wilma, &amp; Pebbles'
9881
     */
9882
    function escape(string) {
9883
      return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
9884
    }
9885

    
9886
    /**
9887
     * This method returns the first argument provided to it.
9888
     *
9889
     * @static
9890
     * @memberOf _
9891
     * @category Utilities
9892
     * @param {*} value Any value.
9893
     * @returns {*} Returns `value`.
9894
     * @example
9895
     *
9896
     * var object = { 'name': 'fred' };
9897
     * _.identity(object) === object;
9898
     * // => true
9899
     */
9900
    function identity(value) {
9901
      return value;
9902
    }
9903

    
9904
    /**
9905
     * Adds function properties of a source object to the destination object.
9906
     * If `object` is a function methods will be added to its prototype as well.
9907
     *
9908
     * @static
9909
     * @memberOf _
9910
     * @category Utilities
9911
     * @param {Function|Object} [object=lodash] object The destination object.
9912
     * @param {Object} source The object of functions to add.
9913
     * @param {Object} [options] The options object.
9914
     * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
9915
     * @example
9916
     *
9917
     * function capitalize(string) {
9918
     *   return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
9919
     * }
9920
     *
9921
     * _.mixin({ 'capitalize': capitalize });
9922
     * _.capitalize('fred');
9923
     * // => 'Fred'
9924
     *
9925
     * _('fred').capitalize().value();
9926
     * // => 'Fred'
9927
     *
9928
     * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
9929
     * _('fred').capitalize();
9930
     * // => 'Fred'
9931
     */
9932
    function mixin(object, source, options) {
9933
      var chain = true,
9934
          methodNames = source && functions(source);
9935

    
9936
      if (!source || (!options && !methodNames.length)) {
9937
        if (options == null) {
9938
          options = source;
9939
        }
9940
        ctor = lodashWrapper;
9941
        source = object;
9942
        object = lodash;
9943
        methodNames = functions(source);
9944
      }
9945
      if (options === false) {
9946
        chain = false;
9947
      } else if (isObject(options) && 'chain' in options) {
9948
        chain = options.chain;
9949
      }
9950
      var ctor = object,
9951
          isFunc = isFunction(ctor);
9952

    
9953
      forEach(methodNames, function(methodName) {
9954
        var func = object[methodName] = source[methodName];
9955
        if (isFunc) {
9956
          ctor.prototype[methodName] = function() {
9957
            var chainAll = this.__chain__,
9958
                value = this.__wrapped__,
9959
                args = [value];
9960

    
9961
            push.apply(args, arguments);
9962
            var result = func.apply(object, args);
9963
            if (chain || chainAll) {
9964
              if (value === result && isObject(result)) {
9965
                return this;
9966
              }
9967
              result = new ctor(result);
9968
              result.__chain__ = chainAll;
9969
            }
9970
            return result;
9971
          };
9972
        }
9973
      });
9974
    }
9975

    
9976
    /**
9977
     * Reverts the '_' variable to its previous value and returns a reference to
9978
     * the `lodash` function.
9979
     *
9980
     * @static
9981
     * @memberOf _
9982
     * @category Utilities
9983
     * @returns {Function} Returns the `lodash` function.
9984
     * @example
9985
     *
9986
     * var lodash = _.noConflict();
9987
     */
9988
    function noConflict() {
9989
      context._ = oldDash;
9990
      return this;
9991
    }
9992

    
9993
    /**
9994
     * A no-operation function.
9995
     *
9996
     * @static
9997
     * @memberOf _
9998
     * @category Utilities
9999
     * @example
10000
     *
10001
     * var object = { 'name': 'fred' };
10002
     * _.noop(object) === undefined;
10003
     * // => true
10004
     */
10005
    function noop() {
10006
      // no operation performed
10007
    }
10008

    
10009
    /**
10010
     * Gets the number of milliseconds that have elapsed since the Unix epoch
10011
     * (1 January 1970 00:00:00 UTC).
10012
     *
10013
     * @static
10014
     * @memberOf _
10015
     * @category Utilities
10016
     * @example
10017
     *
10018
     * var stamp = _.now();
10019
     * _.defer(function() { console.log(_.now() - stamp); });
10020
     * // => logs the number of milliseconds it took for the deferred function to be called
10021
     */
10022
    var now = isNative(now = Date.now) && now || function() {
10023
      return new Date().getTime();
10024
    };
10025

    
10026
    /**
10027
     * Converts the given value into an integer of the specified radix.
10028
     * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
10029
     * `value` is a hexadecimal, in which case a `radix` of `16` is used.
10030
     *
10031
     * Note: This method avoids differences in native ES3 and ES5 `parseInt`
10032
     * implementations. See http://es5.github.io/#E.
10033
     *
10034
     * @static
10035
     * @memberOf _
10036
     * @category Utilities
10037
     * @param {string} value The value to parse.
10038
     * @param {number} [radix] The radix used to interpret the value to parse.
10039
     * @returns {number} Returns the new integer value.
10040
     * @example
10041
     *
10042
     * _.parseInt('08');
10043
     * // => 8
10044
     */
10045
    var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
10046
      // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
10047
      return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
10048
    };
10049

    
10050
    /**
10051
     * Creates a "_.pluck" style function, which returns the `key` value of a
10052
     * given object.
10053
     *
10054
     * @static
10055
     * @memberOf _
10056
     * @category Utilities
10057
     * @param {string} key The name of the property to retrieve.
10058
     * @returns {Function} Returns the new function.
10059
     * @example
10060
     *
10061
     * var characters = [
10062
     *   { 'name': 'fred',   'age': 40 },
10063
     *   { 'name': 'barney', 'age': 36 }
10064
     * ];
10065
     *
10066
     * var getName = _.property('name');
10067
     *
10068
     * _.map(characters, getName);
10069
     * // => ['barney', 'fred']
10070
     *
10071
     * _.sortBy(characters, getName);
10072
     * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred',   'age': 40 }]
10073
     */
10074
    function property(key) {
10075
      return function(object) {
10076
        return object[key];
10077
      };
10078
    }
10079

    
10080
    /**
10081
     * Produces a random number between `min` and `max` (inclusive). If only one
10082
     * argument is provided a number between `0` and the given number will be
10083
     * returned. If `floating` is truey or either `min` or `max` are floats a
10084
     * floating-point number will be returned instead of an integer.
10085
     *
10086
     * @static
10087
     * @memberOf _
10088
     * @category Utilities
10089
     * @param {number} [min=0] The minimum possible value.
10090
     * @param {number} [max=1] The maximum possible value.
10091
     * @param {boolean} [floating=false] Specify returning a floating-point number.
10092
     * @returns {number} Returns a random number.
10093
     * @example
10094
     *
10095
     * _.random(0, 5);
10096
     * // => an integer between 0 and 5
10097
     *
10098
     * _.random(5);
10099
     * // => also an integer between 0 and 5
10100
     *
10101
     * _.random(5, true);
10102
     * // => a floating-point number between 0 and 5
10103
     *
10104
     * _.random(1.2, 5.2);
10105
     * // => a floating-point number between 1.2 and 5.2
10106
     */
10107
    function random(min, max, floating) {
10108
      var noMin = min == null,
10109
          noMax = max == null;
10110

    
10111
      if (floating == null) {
10112
        if (typeof min == 'boolean' && noMax) {
10113
          floating = min;
10114
          min = 1;
10115
        }
10116
        else if (!noMax && typeof max == 'boolean') {
10117
          floating = max;
10118
          noMax = true;
10119
        }
10120
      }
10121
      if (noMin && noMax) {
10122
        max = 1;
10123
      }
10124
      min = +min || 0;
10125
      if (noMax) {
10126
        max = min;
10127
        min = 0;
10128
      } else {
10129
        max = +max || 0;
10130
      }
10131
      if (floating || min % 1 || max % 1) {
10132
        var rand = nativeRandom();
10133
        return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
10134
      }
10135
      return baseRandom(min, max);
10136
    }
10137

    
10138
    /**
10139
     * Resolves the value of property `key` on `object`. If `key` is a function
10140
     * it will be invoked with the `this` binding of `object` and its result returned,
10141
     * else the property value is returned. If `object` is falsey then `undefined`
10142
     * is returned.
10143
     *
10144
     * @static
10145
     * @memberOf _
10146
     * @category Utilities
10147
     * @param {Object} object The object to inspect.
10148
     * @param {string} key The name of the property to resolve.
10149
     * @returns {*} Returns the resolved value.
10150
     * @example
10151
     *
10152
     * var object = {
10153
     *   'cheese': 'crumpets',
10154
     *   'stuff': function() {
10155
     *     return 'nonsense';
10156
     *   }
10157
     * };
10158
     *
10159
     * _.result(object, 'cheese');
10160
     * // => 'crumpets'
10161
     *
10162
     * _.result(object, 'stuff');
10163
     * // => 'nonsense'
10164
     */
10165
    function result(object, key) {
10166
      if (object) {
10167
        var value = object[key];
10168
        return isFunction(value) ? object[key]() : value;
10169
      }
10170
    }
10171

    
10172
    /**
10173
     * A micro-templating method that handles arbitrary delimiters, preserves
10174
     * whitespace, and correctly escapes quotes within interpolated code.
10175
     *
10176
     * Note: In the development build, `_.template` utilizes sourceURLs for easier
10177
     * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
10178
     *
10179
     * For more information on precompiling templates see:
10180
     * http://lodash.com/custom-builds
10181
     *
10182
     * For more information on Chrome extension sandboxes see:
10183
     * http://developer.chrome.com/stable/extensions/sandboxingEval.html
10184
     *
10185
     * @static
10186
     * @memberOf _
10187
     * @category Utilities
10188
     * @param {string} text The template text.
10189
     * @param {Object} data The data object used to populate the text.
10190
     * @param {Object} [options] The options object.
10191
     * @param {RegExp} [options.escape] The "escape" delimiter.
10192
     * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
10193
     * @param {Object} [options.imports] An object to import into the template as local variables.
10194
     * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
10195
     * @param {string} [sourceURL] The sourceURL of the template's compiled source.
10196
     * @param {string} [variable] The data object variable name.
10197
     * @returns {Function|string} Returns a compiled function when no `data` object
10198
     *  is given, else it returns the interpolated text.
10199
     * @example
10200
     *
10201
     * // using the "interpolate" delimiter to create a compiled template
10202
     * var compiled = _.template('hello <%= name %>');
10203
     * compiled({ 'name': 'fred' });
10204
     * // => 'hello fred'
10205
     *
10206
     * // using the "escape" delimiter to escape HTML in data property values
10207
     * _.template('<b><%- value %></b>', { 'value': '<script>' });
10208
     * // => '<b>&lt;script&gt;</b>'
10209
     *
10210
     * // using the "evaluate" delimiter to generate HTML
10211
     * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
10212
     * _.template(list, { 'people': ['fred', 'barney'] });
10213
     * // => '<li>fred</li><li>barney</li>'
10214
     *
10215
     * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
10216
     * _.template('hello ${ name }', { 'name': 'pebbles' });
10217
     * // => 'hello pebbles'
10218
     *
10219
     * // using the internal `print` function in "evaluate" delimiters
10220
     * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
10221
     * // => 'hello barney!'
10222
     *
10223
     * // using a custom template delimiters
10224
     * _.templateSettings = {
10225
     *   'interpolate': /{{([\s\S]+?)}}/g
10226
     * };
10227
     *
10228
     * _.template('hello {{ name }}!', { 'name': 'mustache' });
10229
     * // => 'hello mustache!'
10230
     *
10231
     * // using the `imports` option to import jQuery
10232
     * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
10233
     * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
10234
     * // => '<li>fred</li><li>barney</li>'
10235
     *
10236
     * // using the `sourceURL` option to specify a custom sourceURL for the template
10237
     * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
10238
     * compiled(data);
10239
     * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
10240
     *
10241
     * // using the `variable` option to ensure a with-statement isn't used in the compiled template
10242
     * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
10243
     * compiled.source;
10244
     * // => function(data) {
10245
     *   var __t, __p = '', __e = _.escape;
10246
     *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
10247
     *   return __p;
10248
     * }
10249
     *
10250
     * // using the `source` property to inline compiled templates for meaningful
10251
     * // line numbers in error messages and a stack trace
10252
     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
10253
     *   var JST = {\
10254
     *     "main": ' + _.template(mainText).source + '\
10255
     *   };\
10256
     * ');
10257
     */
10258
    function template(text, data, options) {
10259
      // based on John Resig's `tmpl` implementation
10260
      // http://ejohn.org/blog/javascript-micro-templating/
10261
      // and Laura Doktorova's doT.js
10262
      // https://github.com/olado/doT
10263
      var settings = lodash.templateSettings;
10264
      text = String(text || '');
10265

    
10266
      // avoid missing dependencies when `iteratorTemplate` is not defined
10267
      options = defaults({}, options, settings);
10268

    
10269
      var imports = defaults({}, options.imports, settings.imports),
10270
          importsKeys = keys(imports),
10271
          importsValues = values(imports);
10272

    
10273
      var isEvaluating,
10274
          index = 0,
10275
          interpolate = options.interpolate || reNoMatch,
10276
          source = "__p += '";
10277

    
10278
      // compile the regexp to match each delimiter
10279
      var reDelimiters = RegExp(
10280
        (options.escape || reNoMatch).source + '|' +
10281
        interpolate.source + '|' +
10282
        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
10283
        (options.evaluate || reNoMatch).source + '|$'
10284
      , 'g');
10285

    
10286
      text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
10287
        interpolateValue || (interpolateValue = esTemplateValue);
10288

    
10289
        // escape characters that cannot be included in string literals
10290
        source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
10291

    
10292
        // replace delimiters with snippets
10293
        if (escapeValue) {
10294
          source += "' +\n__e(" + escapeValue + ") +\n'";
10295
        }
10296
        if (evaluateValue) {
10297
          isEvaluating = true;
10298
          source += "';\n" + evaluateValue + ";\n__p += '";
10299
        }
10300
        if (interpolateValue) {
10301
          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
10302
        }
10303
        index = offset + match.length;
10304

    
10305
        // the JS engine embedded in Adobe products requires returning the `match`
10306
        // string in order to produce the correct `offset` value
10307
        return match;
10308
      });
10309

    
10310
      source += "';\n";
10311

    
10312
      // if `variable` is not specified, wrap a with-statement around the generated
10313
      // code to add the data object to the top of the scope chain
10314
      var variable = options.variable,
10315
          hasVariable = variable;
10316

    
10317
      if (!hasVariable) {
10318
        variable = 'obj';
10319
        source = 'with (' + variable + ') {\n' + source + '\n}\n';
10320
      }
10321
      // cleanup code by stripping empty strings
10322
      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
10323
        .replace(reEmptyStringMiddle, '$1')
10324
        .replace(reEmptyStringTrailing, '$1;');
10325

    
10326
      // frame code as the function body
10327
      source = 'function(' + variable + ') {\n' +
10328
        (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
10329
        "var __t, __p = '', __e = _.escape" +
10330
        (isEvaluating
10331
          ? ', __j = Array.prototype.join;\n' +
10332
            "function print() { __p += __j.call(arguments, '') }\n"
10333
          : ';\n'
10334
        ) +
10335
        source +
10336
        'return __p\n}';
10337

    
10338
      // Use a sourceURL for easier debugging.
10339
      // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
10340
      var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
10341

    
10342
      try {
10343
        var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
10344
      } catch(e) {
10345
        e.source = source;
10346
        throw e;
10347
      }
10348
      if (data) {
10349
        return result(data);
10350
      }
10351
      // provide the compiled function's source by its `toString` method, in
10352
      // supported environments, or the `source` property as a convenience for
10353
      // inlining compiled templates during the build process
10354
      result.source = source;
10355
      return result;
10356
    }
10357

    
10358
    /**
10359
     * Executes the callback `n` times, returning an array of the results
10360
     * of each callback execution. The callback is bound to `thisArg` and invoked
10361
     * with one argument; (index).
10362
     *
10363
     * @static
10364
     * @memberOf _
10365
     * @category Utilities
10366
     * @param {number} n The number of times to execute the callback.
10367
     * @param {Function} callback The function called per iteration.
10368
     * @param {*} [thisArg] The `this` binding of `callback`.
10369
     * @returns {Array} Returns an array of the results of each `callback` execution.
10370
     * @example
10371
     *
10372
     * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
10373
     * // => [3, 6, 4]
10374
     *
10375
     * _.times(3, function(n) { mage.castSpell(n); });
10376
     * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
10377
     *
10378
     * _.times(3, function(n) { this.cast(n); }, mage);
10379
     * // => also calls `mage.castSpell(n)` three times
10380
     */
10381
    function times(n, callback, thisArg) {
10382
      n = (n = +n) > -1 ? n : 0;
10383
      var index = -1,
10384
          result = Array(n);
10385

    
10386
      callback = baseCreateCallback(callback, thisArg, 1);
10387
      while (++index < n) {
10388
        result[index] = callback(index);
10389
      }
10390
      return result;
10391
    }
10392

    
10393
    /**
10394
     * The inverse of `_.escape` this method converts the HTML entities
10395
     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
10396
     * corresponding characters.
10397
     *
10398
     * @static
10399
     * @memberOf _
10400
     * @category Utilities
10401
     * @param {string} string The string to unescape.
10402
     * @returns {string} Returns the unescaped string.
10403
     * @example
10404
     *
10405
     * _.unescape('Fred, Barney &amp; Pebbles');
10406
     * // => 'Fred, Barney & Pebbles'
10407
     */
10408
    function unescape(string) {
10409
      return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
10410
    }
10411

    
10412
    /**
10413
     * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
10414
     *
10415
     * @static
10416
     * @memberOf _
10417
     * @category Utilities
10418
     * @param {string} [prefix] The value to prefix the ID with.
10419
     * @returns {string} Returns the unique ID.
10420
     * @example
10421
     *
10422
     * _.uniqueId('contact_');
10423
     * // => 'contact_104'
10424
     *
10425
     * _.uniqueId();
10426
     * // => '105'
10427
     */
10428
    function uniqueId(prefix) {
10429
      var id = ++idCounter;
10430
      return String(prefix == null ? '' : prefix) + id;
10431
    }
10432

    
10433
    /*--------------------------------------------------------------------------*/
10434

    
10435
    /**
10436
     * Creates a `lodash` object that wraps the given value with explicit
10437
     * method chaining enabled.
10438
     *
10439
     * @static
10440
     * @memberOf _
10441
     * @category Chaining
10442
     * @param {*} value The value to wrap.
10443
     * @returns {Object} Returns the wrapper object.
10444
     * @example
10445
     *
10446
     * var characters = [
10447
     *   { 'name': 'barney',  'age': 36 },
10448
     *   { 'name': 'fred',    'age': 40 },
10449
     *   { 'name': 'pebbles', 'age': 1 }
10450
     * ];
10451
     *
10452
     * var youngest = _.chain(characters)
10453
     *     .sortBy('age')
10454
     *     .map(function(chr) { return chr.name + ' is ' + chr.age; })
10455
     *     .first()
10456
     *     .value();
10457
     * // => 'pebbles is 1'
10458
     */
10459
    function chain(value) {
10460
      value = new lodashWrapper(value);
10461
      value.__chain__ = true;
10462
      return value;
10463
    }
10464

    
10465
    /**
10466
     * Invokes `interceptor` with the `value` as the first argument and then
10467
     * returns `value`. The purpose of this method is to "tap into" a method
10468
     * chain in order to perform operations on intermediate results within
10469
     * the chain.
10470
     *
10471
     * @static
10472
     * @memberOf _
10473
     * @category Chaining
10474
     * @param {*} value The value to provide to `interceptor`.
10475
     * @param {Function} interceptor The function to invoke.
10476
     * @returns {*} Returns `value`.
10477
     * @example
10478
     *
10479
     * _([1, 2, 3, 4])
10480
     *  .tap(function(array) { array.pop(); })
10481
     *  .reverse()
10482
     *  .value();
10483
     * // => [3, 2, 1]
10484
     */
10485
    function tap(value, interceptor) {
10486
      interceptor(value);
10487
      return value;
10488
    }
10489

    
10490
    /**
10491
     * Enables explicit method chaining on the wrapper object.
10492
     *
10493
     * @name chain
10494
     * @memberOf _
10495
     * @category Chaining
10496
     * @returns {*} Returns the wrapper object.
10497
     * @example
10498
     *
10499
     * var characters = [
10500
     *   { 'name': 'barney', 'age': 36 },
10501
     *   { 'name': 'fred',   'age': 40 }
10502
     * ];
10503
     *
10504
     * // without explicit chaining
10505
     * _(characters).first();
10506
     * // => { 'name': 'barney', 'age': 36 }
10507
     *
10508
     * // with explicit chaining
10509
     * _(characters).chain()
10510
     *   .first()
10511
     *   .pick('age')
10512
     *   .value();
10513
     * // => { 'age': 36 }
10514
     */
10515
    function wrapperChain() {
10516
      this.__chain__ = true;
10517
      return this;
10518
    }
10519

    
10520
    /**
10521
     * Produces the `toString` result of the wrapped value.
10522
     *
10523
     * @name toString
10524
     * @memberOf _
10525
     * @category Chaining
10526
     * @returns {string} Returns the string result.
10527
     * @example
10528
     *
10529
     * _([1, 2, 3]).toString();
10530
     * // => '1,2,3'
10531
     */
10532
    function wrapperToString() {
10533
      return String(this.__wrapped__);
10534
    }
10535

    
10536
    /**
10537
     * Extracts the wrapped value.
10538
     *
10539
     * @name valueOf
10540
     * @memberOf _
10541
     * @alias value
10542
     * @category Chaining
10543
     * @returns {*} Returns the wrapped value.
10544
     * @example
10545
     *
10546
     * _([1, 2, 3]).valueOf();
10547
     * // => [1, 2, 3]
10548
     */
10549
    function wrapperValueOf() {
10550
      return this.__wrapped__;
10551
    }
10552

    
10553
    /*--------------------------------------------------------------------------*/
10554

    
10555
    // add functions that return wrapped values when chaining
10556
    lodash.after = after;
10557
    lodash.assign = assign;
10558
    lodash.at = at;
10559
    lodash.bind = bind;
10560
    lodash.bindAll = bindAll;
10561
    lodash.bindKey = bindKey;
10562
    lodash.chain = chain;
10563
    lodash.compact = compact;
10564
    lodash.compose = compose;
10565
    lodash.constant = constant;
10566
    lodash.countBy = countBy;
10567
    lodash.create = create;
10568
    lodash.createCallback = createCallback;
10569
    lodash.curry = curry;
10570
    lodash.debounce = debounce;
10571
    lodash.defaults = defaults;
10572
    lodash.defer = defer;
10573
    lodash.delay = delay;
10574
    lodash.difference = difference;
10575
    lodash.filter = filter;
10576
    lodash.flatten = flatten;
10577
    lodash.forEach = forEach;
10578
    lodash.forEachRight = forEachRight;
10579
    lodash.forIn = forIn;
10580
    lodash.forInRight = forInRight;
10581
    lodash.forOwn = forOwn;
10582
    lodash.forOwnRight = forOwnRight;
10583
    lodash.functions = functions;
10584
    lodash.groupBy = groupBy;
10585
    lodash.indexBy = indexBy;
10586
    lodash.initial = initial;
10587
    lodash.intersection = intersection;
10588
    lodash.invert = invert;
10589
    lodash.invoke = invoke;
10590
    lodash.keys = keys;
10591
    lodash.map = map;
10592
    lodash.mapValues = mapValues;
10593
    lodash.max = max;
10594
    lodash.memoize = memoize;
10595
    lodash.merge = merge;
10596
    lodash.min = min;
10597
    lodash.omit = omit;
10598
    lodash.once = once;
10599
    lodash.pairs = pairs;
10600
    lodash.partial = partial;
10601
    lodash.partialRight = partialRight;
10602
    lodash.pick = pick;
10603
    lodash.pluck = pluck;
10604
    lodash.property = property;
10605
    lodash.pull = pull;
10606
    lodash.range = range;
10607
    lodash.reject = reject;
10608
    lodash.remove = remove;
10609
    lodash.rest = rest;
10610
    lodash.shuffle = shuffle;
10611
    lodash.sortBy = sortBy;
10612
    lodash.tap = tap;
10613
    lodash.throttle = throttle;
10614
    lodash.times = times;
10615
    lodash.toArray = toArray;
10616
    lodash.transform = transform;
10617
    lodash.union = union;
10618
    lodash.uniq = uniq;
10619
    lodash.values = values;
10620
    lodash.where = where;
10621
    lodash.without = without;
10622
    lodash.wrap = wrap;
10623
    lodash.xor = xor;
10624
    lodash.zip = zip;
10625
    lodash.zipObject = zipObject;
10626

    
10627
    // add aliases
10628
    lodash.collect = map;
10629
    lodash.drop = rest;
10630
    lodash.each = forEach;
10631
    lodash.eachRight = forEachRight;
10632
    lodash.extend = assign;
10633
    lodash.methods = functions;
10634
    lodash.object = zipObject;
10635
    lodash.select = filter;
10636
    lodash.tail = rest;
10637
    lodash.unique = uniq;
10638
    lodash.unzip = zip;
10639

    
10640
    // add functions to `lodash.prototype`
10641
    mixin(lodash);
10642

    
10643
    /*--------------------------------------------------------------------------*/
10644

    
10645
    // add functions that return unwrapped values when chaining
10646
    lodash.clone = clone;
10647
    lodash.cloneDeep = cloneDeep;
10648
    lodash.contains = contains;
10649
    lodash.escape = escape;
10650
    lodash.every = every;
10651
    lodash.find = find;
10652
    lodash.findIndex = findIndex;
10653
    lodash.findKey = findKey;
10654
    lodash.findLast = findLast;
10655
    lodash.findLastIndex = findLastIndex;
10656
    lodash.findLastKey = findLastKey;
10657
    lodash.has = has;
10658
    lodash.identity = identity;
10659
    lodash.indexOf = indexOf;
10660
    lodash.isArguments = isArguments;
10661
    lodash.isArray = isArray;
10662
    lodash.isBoolean = isBoolean;
10663
    lodash.isDate = isDate;
10664
    lodash.isElement = isElement;
10665
    lodash.isEmpty = isEmpty;
10666
    lodash.isEqual = isEqual;
10667
    lodash.isFinite = isFinite;
10668
    lodash.isFunction = isFunction;
10669
    lodash.isNaN = isNaN;
10670
    lodash.isNull = isNull;
10671
    lodash.isNumber = isNumber;
10672
    lodash.isObject = isObject;
10673
    lodash.isPlainObject = isPlainObject;
10674
    lodash.isRegExp = isRegExp;
10675
    lodash.isString = isString;
10676
    lodash.isUndefined = isUndefined;
10677
    lodash.lastIndexOf = lastIndexOf;
10678
    lodash.mixin = mixin;
10679
    lodash.noConflict = noConflict;
10680
    lodash.noop = noop;
10681
    lodash.now = now;
10682
    lodash.parseInt = parseInt;
10683
    lodash.random = random;
10684
    lodash.reduce = reduce;
10685
    lodash.reduceRight = reduceRight;
10686
    lodash.result = result;
10687
    lodash.runInContext = runInContext;
10688
    lodash.size = size;
10689
    lodash.some = some;
10690
    lodash.sortedIndex = sortedIndex;
10691
    lodash.template = template;
10692
    lodash.unescape = unescape;
10693
    lodash.uniqueId = uniqueId;
10694

    
10695
    // add aliases
10696
    lodash.all = every;
10697
    lodash.any = some;
10698
    lodash.detect = find;
10699
    lodash.findWhere = find;
10700
    lodash.foldl = reduce;
10701
    lodash.foldr = reduceRight;
10702
    lodash.include = contains;
10703
    lodash.inject = reduce;
10704

    
10705
    mixin(function() {
10706
      var source = {}
10707
      forOwn(lodash, function(func, methodName) {
10708
        if (!lodash.prototype[methodName]) {
10709
          source[methodName] = func;
10710
        }
10711
      });
10712
      return source;
10713
    }(), false);
10714

    
10715
    /*--------------------------------------------------------------------------*/
10716

    
10717
    // add functions capable of returning wrapped and unwrapped values when chaining
10718
    lodash.first = first;
10719
    lodash.last = last;
10720
    lodash.sample = sample;
10721

    
10722
    // add aliases
10723
    lodash.take = first;
10724
    lodash.head = first;
10725

    
10726
    forOwn(lodash, function(func, methodName) {
10727
      var callbackable = methodName !== 'sample';
10728
      if (!lodash.prototype[methodName]) {
10729
        lodash.prototype[methodName]= function(n, guard) {
10730
          var chainAll = this.__chain__,
10731
              result = func(this.__wrapped__, n, guard);
10732

    
10733
          return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
10734
            ? result
10735
            : new lodashWrapper(result, chainAll);
10736
        };
10737
      }
10738
    });
10739

    
10740
    /*--------------------------------------------------------------------------*/
10741

    
10742
    /**
10743
     * The semantic version number.
10744
     *
10745
     * @static
10746
     * @memberOf _
10747
     * @type string
10748
     */
10749
    lodash.VERSION = '2.4.1';
10750

    
10751
    // add "Chaining" functions to the wrapper
10752
    lodash.prototype.chain = wrapperChain;
10753
    lodash.prototype.toString = wrapperToString;
10754
    lodash.prototype.value = wrapperValueOf;
10755
    lodash.prototype.valueOf = wrapperValueOf;
10756

    
10757
    // add `Array` functions that return unwrapped values
10758
    forEach(['join', 'pop', 'shift'], function(methodName) {
10759
      var func = arrayRef[methodName];
10760
      lodash.prototype[methodName] = function() {
10761
        var chainAll = this.__chain__,
10762
            result = func.apply(this.__wrapped__, arguments);
10763

    
10764
        return chainAll
10765
          ? new lodashWrapper(result, chainAll)
10766
          : result;
10767
      };
10768
    });
10769

    
10770
    // add `Array` functions that return the existing wrapped value
10771
    forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
10772
      var func = arrayRef[methodName];
10773
      lodash.prototype[methodName] = function() {
10774
        func.apply(this.__wrapped__, arguments);
10775
        return this;
10776
      };
10777
    });
10778

    
10779
    // add `Array` functions that return new wrapped values
10780
    forEach(['concat', 'slice', 'splice'], function(methodName) {
10781
      var func = arrayRef[methodName];
10782
      lodash.prototype[methodName] = function() {
10783
        return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
10784
      };
10785
    });
10786

    
10787
    return lodash;
10788
  }
10789

    
10790
  /*--------------------------------------------------------------------------*/
10791

    
10792
  // expose Lo-Dash
10793
  var _ = runInContext();
10794

    
10795
  // some AMD build optimizers like r.js check for condition patterns like the following:
10796
  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
10797
    // Expose Lo-Dash to the global object even when an AMD loader is present in
10798
    // case Lo-Dash is loaded with a RequireJS shim config.
10799
    // See http://requirejs.org/docs/api.html#config-shim
10800
    root._ = _;
10801

    
10802
    // define as an anonymous module so, through path mapping, it can be
10803
    // referenced as the "underscore" module
10804
    define(function() {
10805
      return _;
10806
    });
10807
  }
10808
  // check for `exports` after `define` in case a build optimizer adds an `exports` object
10809
  else if (freeExports && freeModule) {
10810
    // in Node.js or RingoJS
10811
    if (moduleExports) {
10812
      (freeModule.exports = _)._ = _;
10813
    }
10814
    // in Narwhal or Rhino -require
10815
    else {
10816
      freeExports._ = _;
10817
    }
10818
  }
10819
  else {
10820
    // in a browser or Rhino
10821
    root._ = _;
10822
  }
10823
}.call(this));
10824

    
10825
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
10826
},{}]},{},[1])(1)
10827
});
(1-1/2)